Go back to index | PHP CodeBrowser

phpseclib/Crypt/Base.php
  1.    1  <?php
  2.    2 
  3.    3 /**
  4.    4  * Base Class for all Crypt_* cipher classes
  5.    5  *
  6.    6  * PHP versions 4 and 5
  7.    7  *
  8.    8  * Internally for phpseclib developers:
  9.    9  *  If you plan to add a new cipher class, please note following rules:
  10.   10  *
  11.   11  *  - The new Crypt_* cipher class should extend Crypt_Base
  12.   12  *
  13.   13  *  - Following methods are then required to be overridden/overloaded:
  14.   14  *
  15.   15  *    - _encryptBlock()
  16.   16  *
  17.   17  *    - _decryptBlock()
  18.   18  *
  19.   19  *    - _setupKey()
  20.   20  *
  21.   21  *  - All other methods are optional to be overridden/overloaded
  22.   22  *
  23.   23  *  - Look at the source code of the current ciphers how they extend Crypt_Base
  24.   24  *    and take one of them as a start up for the new cipher class.
  25.   25  *
  26.   26  *  - Please read all the other comments/notes/hints here also for each class var/method
  27.   27  *
  28.   28  * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
  29.   29  * of this software and associated documentation files (the "Software"), to deal
  30.   30  * in the Software without restriction, including without limitation the rights
  31.   31  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  32.   32  * copies of the Software, and to permit persons to whom the Software is
  33.   33  * furnished to do so, subject to the following conditions:
  34.   34  *
  35.   35  * The above copyright notice and this permission notice shall be included in
  36.   36  * all copies or substantial portions of the Software.
  37.   37  *
  38.   38  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  39.   39  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  40.   40  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  41.   41  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  42.   42  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  43.   43  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  44.   44  * THE SOFTWARE.
  45.   45  *
  46.   46  * @category  Crypt
  47.   47  * @package   Crypt_Base
  48.   48  * @author    Jim Wigginton <terrafrost@php.net>
  49.   49  * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
  50.   50  * @copyright 2007 Jim Wigginton
  51.   51  * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  52.   52  * @link      http://phpseclib.sourceforge.net
  53.   53  */
  54.   54 
  55.   55 /**#@+
  56.   56  * @access public
  57.   57  * @see self::encrypt()
  58.   58  * @see self::decrypt()
  59.   59  */
  60.   60 /**
  61.   61  * Encrypt / decrypt using the Counter mode.
  62.   62  *
  63.   63  * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
  64.   64  *
  65.   65  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
  66.   66  */
  67.   67 define('CRYPT_MODE_CTR', -1);
  68.   68 /**
  69.   69  * Encrypt / decrypt using the Electronic Code Book mode.
  70.   70  *
  71.   71  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
  72.   72  */
  73.   73 define('CRYPT_MODE_ECB'1);
  74.   74 /**
  75.   75  * Encrypt / decrypt using the Code Book Chaining mode.
  76.   76  *
  77.   77  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
  78.   78  */
  79.   79 define('CRYPT_MODE_CBC'2);
  80.   80 /**
  81.   81  * Encrypt / decrypt using the Cipher Feedback mode.
  82.   82  *
  83.   83  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
  84.   84  */
  85.   85 define('CRYPT_MODE_CFB'3);
  86.   86 /**
  87.   87  * Encrypt / decrypt using the Output Feedback mode.
  88.   88  *
  89.   89  * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
  90.   90  */
  91.   91 define('CRYPT_MODE_OFB'4);
  92.   92 /**
  93.   93  * Encrypt / decrypt using streaming mode.
  94.   94  */
  95.   95 define('CRYPT_MODE_STREAM'5);
  96.   96 /**#@-*/
  97.   97 
  98.   98 /**#@+
  99.   99  * @access private
  100.  100  * @see self::Crypt_Base()
  101.  101  * @internal These constants are for internal use only
  102.  102  */
  103.  103 /**
  104.  104  * Base value for the internal implementation $engine switch
  105.  105  */
  106.  106 define('CRYPT_ENGINE_INTERNAL'1);
  107.  107 /**
  108.  108  * Base value for the mcrypt implementation $engine switch
  109.  109  */
  110.  110 define('CRYPT_ENGINE_MCRYPT'2);
  111.  111 /**
  112.  112  * Base value for the OpenSSL implementation $engine switch
  113.  113  */
  114.  114 define('CRYPT_ENGINE_OPENSSL'3);
  115.  115 /**#@-*/
  116.  116 
  117.  117 /**
  118.  118  * Base Class for all Crypt_* cipher classes
  119.  119  *
  120.  120  * @package Crypt_Base
  121.  121  * @author  Jim Wigginton <terrafrost@php.net>
  122.  122  * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
  123.  123  * @access  public
  124.  124  */
  125.  125 class Crypt_Base
  126.  126 {
  127.  127     /**
  128.  128      * The Encryption Mode
  129.  129      *
  130.  130      * @see self::Crypt_Base()
  131.  131      * @var int
  132.  132      * @access private
  133.  133      */
  134.  134     var $mode;
  135.  135 
  136.  136     /**
  137.  137      * The Block Length of the block cipher
  138.  138      *
  139.  139      * @var int
  140.  140      * @access private
  141.  141      */
  142.  142     var $block_size 16;
  143.  143 
  144.  144     /**
  145.  145      * The Key
  146.  146      *
  147.  147      * @see self::setKey()
  148.  148      * @var string
  149.  149      * @access private
  150.  150      */
  151.  151     var $key "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  152.  152 
  153.  153     /**
  154.  154      * The Initialization Vector
  155.  155      *
  156.  156      * @see self::setIV()
  157.  157      * @var string
  158.  158      * @access private
  159.  159      */
  160.  160     var $iv;
  161.  161 
  162.  162     /**
  163.  163      * A "sliding" Initialization Vector
  164.  164      *
  165.  165      * @see self::enableContinuousBuffer()
  166.  166      * @see self::_clearBuffers()
  167.  167      * @var string
  168.  168      * @access private
  169.  169      */
  170.  170     var $encryptIV;
  171.  171 
  172.  172     /**
  173.  173      * A "sliding" Initialization Vector
  174.  174      *
  175.  175      * @see self::enableContinuousBuffer()
  176.  176      * @see self::_clearBuffers()
  177.  177      * @var string
  178.  178      * @access private
  179.  179      */
  180.  180     var $decryptIV;
  181.  181 
  182.  182     /**
  183.  183      * Continuous Buffer status
  184.  184      *
  185.  185      * @see self::enableContinuousBuffer()
  186.  186      * @var bool
  187.  187      * @access private
  188.  188      */
  189.  189     var $continuousBuffer false;
  190.  190 
  191.  191     /**
  192.  192      * Encryption buffer for CTR, OFB and CFB modes
  193.  193      *
  194.  194      * @see self::encrypt()
  195.  195      * @see self::_clearBuffers()
  196.  196      * @var array
  197.  197      * @access private
  198.  198      */
  199.  199     var $enbuffer;
  200.  200 
  201.  201     /**
  202.  202      * Decryption buffer for CTR, OFB and CFB modes
  203.  203      *
  204.  204      * @see self::decrypt()
  205.  205      * @see self::_clearBuffers()
  206.  206      * @var array
  207.  207      * @access private
  208.  208      */
  209.  209     var $debuffer;
  210.  210 
  211.  211     /**
  212.  212      * mcrypt resource for encryption
  213.  213      *
  214.  214      * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
  215.  215      * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
  216.  216      *
  217.  217      * @see self::encrypt()
  218.  218      * @var resource
  219.  219      * @access private
  220.  220      */
  221.  221     var $enmcrypt;
  222.  222 
  223.  223     /**
  224.  224      * mcrypt resource for decryption
  225.  225      *
  226.  226      * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
  227.  227      * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
  228.  228      *
  229.  229      * @see self::decrypt()
  230.  230      * @var resource
  231.  231      * @access private
  232.  232      */
  233.  233     var $demcrypt;
  234.  234 
  235.  235     /**
  236.  236      * Does the enmcrypt resource need to be (re)initialized?
  237.  237      *
  238.  238      * @see Crypt_Twofish::setKey()
  239.  239      * @see Crypt_Twofish::setIV()
  240.  240      * @var bool
  241.  241      * @access private
  242.  242      */
  243.  243     var $enchanged true;
  244.  244 
  245.  245     /**
  246.  246      * Does the demcrypt resource need to be (re)initialized?
  247.  247      *
  248.  248      * @see Crypt_Twofish::setKey()
  249.  249      * @see Crypt_Twofish::setIV()
  250.  250      * @var bool
  251.  251      * @access private
  252.  252      */
  253.  253     var $dechanged true;
  254.  254 
  255.  255     /**
  256.  256      * mcrypt resource for CFB mode
  257.  257      *
  258.  258      * mcrypt's CFB mode, in (and only in) buffered context,
  259.  259      * is broken, so phpseclib implements the CFB mode by it self,
  260.  260      * even when the mcrypt php extension is available.
  261.  261      *
  262.  262      * In order to do the CFB-mode work (fast) phpseclib
  263.  263      * use a separate ECB-mode mcrypt resource.
  264.  264      *
  265.  265      * @link http://phpseclib.sourceforge.net/cfb-demo.phps
  266.  266      * @see self::encrypt()
  267.  267      * @see self::decrypt()
  268.  268      * @see self::_setupMcrypt()
  269.  269      * @var resource
  270.  270      * @access private
  271.  271      */
  272.  272     var $ecb;
  273.  273 
  274.  274     /**
  275.  275      * Optimizing value while CFB-encrypting
  276.  276      *
  277.  277      * Only relevant if $continuousBuffer enabled
  278.  278      * and $engine == CRYPT_ENGINE_MCRYPT
  279.  279      *
  280.  280      * It's faster to re-init $enmcrypt if
  281.  281      * $buffer bytes > $cfb_init_len than
  282.  282      * using the $ecb resource furthermore.
  283.  283      *
  284.  284      * This value depends of the chosen cipher
  285.  285      * and the time it would be needed for it's
  286.  286      * initialization [by mcrypt_generic_init()]
  287.  287      * which, typically, depends on the complexity
  288.  288      * on its internaly Key-expanding algorithm.
  289.  289      *
  290.  290      * @see self::encrypt()
  291.  291      * @var int
  292.  292      * @access private
  293.  293      */
  294.  294     var $cfb_init_len 600;
  295.  295 
  296.  296     /**
  297.  297      * Does internal cipher state need to be (re)initialized?
  298.  298      *
  299.  299      * @see self::setKey()
  300.  300      * @see self::setIV()
  301.  301      * @see self::disableContinuousBuffer()
  302.  302      * @var bool
  303.  303      * @access private
  304.  304      */
  305.  305     var $changed true;
  306.  306 
  307.  307     /**
  308.  308      * Padding status
  309.  309      *
  310.  310      * @see self::enablePadding()
  311.  311      * @var bool
  312.  312      * @access private
  313.  313      */
  314.  314     var $padding true;
  315.  315 
  316.  316     /**
  317.  317      * Is the mode one that is paddable?
  318.  318      *
  319.  319      * @see self::Crypt_Base()
  320.  320      * @var bool
  321.  321      * @access private
  322.  322      */
  323.  323     var $paddable false;
  324.  324 
  325.  325     /**
  326.  326      * Holds which crypt engine internaly should be use,
  327.  327      * which will be determined automatically on __construct()
  328.  328      *
  329.  329      * Currently available $engines are:
  330.  330      * - CRYPT_ENGINE_OPENSSL  (very fast, php-extension: openssl, extension_loaded('openssl') required)
  331.  331      * - CRYPT_ENGINE_MCRYPT   (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
  332.  332      * - CRYPT_ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
  333.  333      *
  334.  334      * @see self::_setEngine()
  335.  335      * @see self::encrypt()
  336.  336      * @see self::decrypt()
  337.  337      * @var int
  338.  338      * @access private
  339.  339      */
  340.  340     var $engine;
  341.  341 
  342.  342     /**
  343.  343      * Holds the preferred crypt engine
  344.  344      *
  345.  345      * @see self::_setEngine()
  346.  346      * @see self::setPreferredEngine()
  347.  347      * @var int
  348.  348      * @access private
  349.  349      */
  350.  350     var $preferredEngine;
  351.  351 
  352.  352     /**
  353.  353      * The mcrypt specific name of the cipher
  354.  354      *
  355.  355      * Only used if $engine == CRYPT_ENGINE_MCRYPT
  356.  356      *
  357.  357      * @link http://www.php.net/mcrypt_module_open
  358.  358      * @link http://www.php.net/mcrypt_list_algorithms
  359.  359      * @see self::_setupMcrypt()
  360.  360      * @var string
  361.  361      * @access private
  362.  362      */
  363.  363     var $cipher_name_mcrypt;
  364.  364 
  365.  365     /**
  366.  366      * The openssl specific name of the cipher
  367.  367      *
  368.  368      * Only used if $engine == CRYPT_ENGINE_OPENSSL
  369.  369      *
  370.  370      * @link http://www.php.net/openssl-get-cipher-methods
  371.  371      * @var string
  372.  372      * @access private
  373.  373      */
  374.  374     var $cipher_name_openssl;
  375.  375 
  376.  376     /**
  377.  377      * The openssl specific name of the cipher in ECB mode
  378.  378      *
  379.  379      * If OpenSSL does not support the mode we're trying to use (CTR)
  380.  380      * it can still be emulated with ECB mode.
  381.  381      *
  382.  382      * @link http://www.php.net/openssl-get-cipher-methods
  383.  383      * @var string
  384.  384      * @access private
  385.  385      */
  386.  386     var $cipher_name_openssl_ecb;
  387.  387 
  388.  388     /**
  389.  389      * The default salt used by setPassword()
  390.  390      *
  391.  391      * @see self::setPassword()
  392.  392      * @var string
  393.  393      * @access private
  394.  394      */
  395.  395     var $password_default_salt 'phpseclib/salt';
  396.  396 
  397.  397     /**
  398.  398      * The namespace used by the cipher for its constants.
  399.  399      *
  400.  400      * ie: AES.php is using CRYPT_AES_MODE_* for its constants
  401.  401      *     so $const_namespace is AES
  402.  402      *
  403.  403      *     DES.php is using CRYPT_DES_MODE_* for its constants
  404.  404      *     so $const_namespace is DES... and so on
  405.  405      *
  406.  406      * All CRYPT_<$const_namespace>_MODE_* are aliases of
  407.  407      * the generic CRYPT_MODE_* constants, so both could be used
  408.  408      * for each cipher.
  409.  409      *
  410.  410      * Example:
  411.  411      * $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode
  412.  412      * $aes = new Crypt_AES(CRYPT_MODE_CFB);     // identical
  413.  413      *
  414.  414      * @see self::Crypt_Base()
  415.  415      * @var string
  416.  416      * @access private
  417.  417      */
  418.  418     var $const_namespace;
  419.  419 
  420.  420     /**
  421.  421      * The name of the performance-optimized callback function
  422.  422      *
  423.  423      * Used by encrypt() / decrypt()
  424.  424      * only if $engine == CRYPT_ENGINE_INTERNAL
  425.  425      *
  426.  426      * @see self::encrypt()
  427.  427      * @see self::decrypt()
  428.  428      * @see self::_setupInlineCrypt()
  429.  429      * @see self::$use_inline_crypt
  430.  430      * @var Callback
  431.  431      * @access private
  432.  432      */
  433.  433     var $inline_crypt;
  434.  434 
  435.  435     /**
  436.  436      * Holds whether performance-optimized $inline_crypt() can/should be used.
  437.  437      *
  438.  438      * @see self::encrypt()
  439.  439      * @see self::decrypt()
  440.  440      * @see self::inline_crypt
  441.  441      * @var mixed
  442.  442      * @access private
  443.  443      */
  444.  444     var $use_inline_crypt;
  445.  445 
  446.  446     /**
  447.  447      * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
  448.  448      *
  449.  449      * @see self::_openssl_ctr_process()
  450.  450      * @var bool
  451.  451      * @access private
  452.  452      */
  453.  453     var $openssl_emulate_ctr false;
  454.  454 
  455.  455     /**
  456.  456      * Determines what options are passed to openssl_encrypt/decrypt
  457.  457      *
  458.  458      * @see self::isValidEngine()
  459.  459      * @var mixed
  460.  460      * @access private
  461.  461      */
  462.  462     var $openssl_options;
  463.  463 
  464.  464     /**
  465.  465      * Has the key length explicitly been set or should it be derived from the key, itself?
  466.  466      *
  467.  467      * @see self::setKeyLength()
  468.  468      * @var bool
  469.  469      * @access private
  470.  470      */
  471.  471     var $explicit_key_length false;
  472.  472 
  473.  473     /**
  474.  474      * Don't truncate / null pad key
  475.  475      *
  476.  476      * @see self::_clearBuffers()
  477.  477      * @var bool
  478.  478      * @access private
  479.  479      */
  480.  480     var $skip_key_adjustment false;
  481.  481 
  482.  482     /**
  483.  483      * Default Constructor.
  484.  484      *
  485.  485      * Determines whether or not the mcrypt extension should be used.
  486.  486      *
  487.  487      * $mode could be:
  488.  488      *
  489.  489      * - CRYPT_MODE_ECB
  490.  490      *
  491.  491      * - CRYPT_MODE_CBC
  492.  492      *
  493.  493      * - CRYPT_MODE_CTR
  494.  494      *
  495.  495      * - CRYPT_MODE_CFB
  496.  496      *
  497.  497      * - CRYPT_MODE_OFB
  498.  498      *
  499.  499      * (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
  500.  500      *
  501.  501      * If not explicitly set, CRYPT_MODE_CBC will be used.
  502.  502      *
  503.  503      * @param int $mode
  504.  504      * @access public
  505.  505      */
  506.  506     function __construct($mode CRYPT_MODE_CBC)
  507.  507     {
  508.  508         // $mode dependent settings
  509.  509         switch ($mode) {
  510.  510             case CRYPT_MODE_ECB:
  511.  511                 $this->paddable true;
  512.  512                 $this->mode CRYPT_MODE_ECB;
  513.  513                 break;
  514.  514             case CRYPT_MODE_CTR:
  515.  515             case CRYPT_MODE_CFB:
  516.  516             case CRYPT_MODE_OFB:
  517.  517             case CRYPT_MODE_STREAM:
  518.  518                 $this->mode $mode;
  519.  519                 break;
  520.  520             case CRYPT_MODE_CBC:
  521.  521             default:
  522.  522                 $this->paddable true;
  523.  523                 $this->mode CRYPT_MODE_CBC;
  524.  524         }
  525.  525 
  526.  526         $this->_setEngine();
  527.  527 
  528.  528         // Determining whether inline crypting can be used by the cipher
  529.  529         if ($this->use_inline_crypt !== false) {
  530.  530             $this->use_inline_crypt version_compare(PHP_VERSION'5.3.0') >= || function_exists('create_function');
  531.  531         }
  532.  532     }
  533.  533 
  534.  534     /**
  535.  535      * PHP4 compatible Default Constructor.
  536.  536      *
  537.  537      * @see self::__construct()
  538.  538      * @param int $mode
  539.  539      * @access public
  540.  540      */
  541.  541     function Crypt_Base($mode CRYPT_MODE_CBC)
  542.  542     {
  543.  543         $this->__construct($mode);
  544.  544     }
  545.  545 
  546.  546     /**
  547.  547      * Sets the initialization vector. (optional)
  548.  548      *
  549.  549      * SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used.  If not explicitly set, it'll be assumed
  550.  550      * to be all zero's.
  551.  551      *
  552.  552      * @access public
  553.  553      * @param string $iv
  554.  554      * @internal Can be overwritten by a sub class, but does not have to be
  555.  555      */
  556.  556     function setIV($iv)
  557.  557     {
  558.  558         if ($this->mode == CRYPT_MODE_ECB) {
  559.  559             return;
  560.  560         }
  561.  561 
  562.  562         $this->iv $iv;
  563.  563         $this->changed true;
  564.  564     }
  565.  565 
  566.  566     /**
  567.  567      * Sets the key length.
  568.  568      *
  569.  569      * Keys with explicitly set lengths need to be treated accordingly
  570.  570      *
  571.  571      * @access public
  572.  572      * @param int $length
  573.  573      */
  574.  574     function setKeyLength($length)
  575.  575     {
  576.  576         $this->explicit_key_length true;
  577.  577         $this->changed true;
  578.  578         $this->_setEngine();
  579.  579     }
  580.  580 
  581.  581     /**
  582.  582      * Returns the current key length in bits
  583.  583      *
  584.  584      * @access public
  585.  585      * @return int
  586.  586      */
  587.  587     function getKeyLength()
  588.  588     {
  589.  589         return $this->key_length << 3;
  590.  590     }
  591.  591 
  592.  592     /**
  593.  593      * Returns the current block length in bits
  594.  594      *
  595.  595      * @access public
  596.  596      * @return int
  597.  597      */
  598.  598     function getBlockLength()
  599.  599     {
  600.  600         return $this->block_size << 3;
  601.  601     }
  602.  602 
  603.  603     /**
  604.  604      * Sets the key.
  605.  605      *
  606.  606      * The min/max length(s) of the key depends on the cipher which is used.
  607.  607      * If the key not fits the length(s) of the cipher it will paded with null bytes
  608.  608      * up to the closest valid key length.  If the key is more than max length,
  609.  609      * we trim the excess bits.
  610.  610      *
  611.  611      * If the key is not explicitly set, it'll be assumed to be all null bytes.
  612.  612      *
  613.  613      * @access public
  614.  614      * @param string $key
  615.  615      * @internal Could, but not must, extend by the child Crypt_* class
  616.  616      */
  617.  617     function setKey($key)
  618.  618     {
  619.  619         if (!$this->explicit_key_length) {
  620.  620             $this->setKeyLength(strlen($key) << 3);
  621.  621             $this->explicit_key_length false;
  622.  622         }
  623.  623 
  624.  624         $this->key $key;
  625.  625         $this->changed true;
  626.  626         $this->_setEngine();
  627.  627     }
  628.  628 
  629.  629     /**
  630.  630      * Sets the password.
  631.  631      *
  632.  632      * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
  633.  633      *     {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
  634.  634      *         $hash, $salt, $count, $dkLen
  635.  635      *
  636.  636      *         Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
  637.  637      *
  638.  638      * @see Crypt/Hash.php
  639.  639      * @param string $password
  640.  640      * @param string $method
  641.  641      * @return bool
  642.  642      * @access public
  643.  643      * @internal Could, but not must, extend by the child Crypt_* class
  644.  644      */
  645.  645     function setPassword($password$method 'pbkdf2')
  646.  646     {
  647.  647         $key '';
  648.  648 
  649.  649         switch ($method) {
  650.  650             default: // 'pbkdf2' or 'pbkdf1'
  651.  651                 $func_args func_get_args();
  652.  652 
  653.  653                 // Hash function
  654.  654                 $hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
  655.  655 
  656.  656                 // WPA and WPA2 use the SSID as the salt
  657.  657                 $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
  658.  658 
  659.  659                 // RFC2898#section-4.2 uses 1,000 iterations by default
  660.  660                 // WPA and WPA2 use 4,096.
  661.  661                 $count = isset($func_args[4]) ? $func_args[4] : 1000;
  662.  662 
  663.  663                 // Keylength
  664.  664                 if (isset($func_args[5])) {
  665.  665                     $dkLen $func_args[5];
  666.  666                 } else {
  667.  667                     $dkLen $method == 'pbkdf1' $this->key_length $this->key_length;
  668.  668                 }
  669.  669 
  670.  670                 switch (true) {
  671.  671                     case $method == 'pbkdf1':
  672.  672                         if (!class_exists('Crypt_Hash')) {
  673.  673                             include_once 'Crypt/Hash.php';
  674.  674                         }
  675.  675                         $hashObj = new Crypt_Hash();
  676.  676                         $hashObj->setHash($hash);
  677.  677                         if ($dkLen $hashObj->getLength()) {
  678.  678                             user_error('Derived key too long');
  679.  679                             return false;
  680.  680                         }
  681.  681                         $t $password $salt;
  682.  682                         for ($i 0$i $count; ++$i) {
  683.  683                             $t $hashObj->hash($t);
  684.  684                         }
  685.  685                         $key substr($t0$dkLen);
  686.  686 
  687.  687                         $this->setKey(substr($key0$dkLen >> 1));
  688.  688                         $this->setIV(substr($key$dkLen >> 1));
  689.  689 
  690.  690                         return true;
  691.  691                     // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
  692.  692                     case !function_exists('hash_pbkdf2'):
  693.  693                     case !function_exists('hash_algos'):
  694.  694                     case !in_array($hashhash_algos()):
  695.  695                         if (!class_exists('Crypt_Hash')) {
  696.  696                             include_once 'Crypt/Hash.php';
  697.  697                         }
  698.  698                         $i 1;
  699.  699                         while (strlen($key) < $dkLen) {
  700.  700                             $hmac = new Crypt_Hash();
  701.  701                             $hmac->setHash($hash);
  702.  702                             $hmac->setKey($password);
  703.  703                             $f $u $hmac->hash($salt pack('N'$i++));
  704.  704                             for ($j 2$j <= $count; ++$j) {
  705.  705                                 $u $hmac->hash($u);
  706.  706                                 $f^= $u;
  707.  707                             }
  708.  708                             $key.= $f;
  709.  709                         }
  710.  710                         $key substr($key0$dkLen);
  711.  711                         break;
  712.  712                     default:
  713.  713                         $key hash_pbkdf2($hash$password$salt$count$dkLentrue);
  714.  714                 }
  715.  715         }
  716.  716 
  717.  717         $this->setKey($key);
  718.  718 
  719.  719         return true;
  720.  720     }
  721.  721 
  722.  722     /**
  723.  723      * Encrypts a message.
  724.  724      *
  725.  725      * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
  726.  726      * implementations may or may not pad in the same manner.  Other common approaches to padding and the reasons why it's
  727.  727      * necessary are discussed in the following
  728.  728      * URL:
  729.  729      *
  730.  730      * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
  731.  731      *
  732.  732      * An alternative to padding is to, separately, send the length of the file.  This is what SSH, in fact, does.
  733.  733      * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
  734.  734      * length.
  735.  735      *
  736.  736      * @see self::decrypt()
  737.  737      * @access public
  738.  738      * @param string $plaintext
  739.  739      * @return string $ciphertext
  740.  740      * @internal Could, but not must, extend by the child Crypt_* class
  741.  741      */
  742.  742     function encrypt($plaintext)
  743.  743     {
  744.  744         if ($this->paddable) {
  745.  745             $plaintext $this->_pad($plaintext);
  746.  746         }
  747.  747 
  748.  748         if ($this->engine === CRYPT_ENGINE_OPENSSL) {
  749.  749             if ($this->changed) {
  750.  750                 $this->_clearBuffers();
  751.  751                 $this->changed false;
  752.  752             }
  753.  753             switch ($this->mode) {
  754.  754                 case CRYPT_MODE_STREAM:
  755.  755                     return openssl_encrypt($plaintext$this->cipher_name_openssl$this->key$this->openssl_options);
  756.  756                 case CRYPT_MODE_ECB:
  757.  757                     $result openssl_encrypt($plaintext$this->cipher_name_openssl$this->key$this->openssl_options);
  758.  758                     return !defined('OPENSSL_RAW_DATA') ? substr($result0, -$this->block_size) : $result;
  759.  759                 case CRYPT_MODE_CBC:
  760.  760                     $result openssl_encrypt($plaintext$this->cipher_name_openssl$this->key$this->openssl_options$this->encryptIV);
  761.  761                     if (!defined('OPENSSL_RAW_DATA')) {
  762.  762                         $result substr($result0, -$this->block_size);
  763.  763                     }
  764.  764                     if ($this->continuousBuffer) {
  765.  765                         $this->encryptIV substr($result, -$this->block_size);
  766.  766                     }
  767.  767                     return $result;
  768.  768                 case CRYPT_MODE_CTR:
  769.  769                     return $this->_openssl_ctr_process($plaintext$this->encryptIV$this->enbuffer);
  770.  770                 case CRYPT_MODE_CFB:
  771.  771                     // cfb loosely routines inspired by openssl's:
  772.  772                     // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
  773.  773                     $ciphertext '';
  774.  774                     if ($this->continuousBuffer) {
  775.  775                         $iv = &$this->encryptIV;
  776.  776                         $pos = &$this->enbuffer['pos'];
  777.  777                     } else {
  778.  778                         $iv $this->encryptIV;
  779.  779                         $pos 0;
  780.  780                     }
  781.  781                     $len strlen($plaintext);
  782.  782                     $i 0;
  783.  783                     if ($pos) {
  784.  784                         $orig_pos $pos;
  785.  785                         $max $this->block_size $pos;
  786.  786                         if ($len >= $max) {
  787.  787                             $i $max;
  788.  788                             $len-= $max;
  789.  789                             $pos 0;
  790.  790                         } else {
  791.  791                             $i $len;
  792.  792                             $pos+= $len;
  793.  793                             $len 0;
  794.  794                         }
  795.  795                         // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
  796.  796                         $ciphertext substr($iv$orig_pos) ^ $plaintext;
  797.  797                         $iv substr_replace($iv$ciphertext$orig_pos$i);
  798.  798                         $plaintext substr($plaintext$i);
  799.  799                     }
  800.  800 
  801.  801                     $overflow $len $this->block_size;
  802.  802 
  803.  803                     if ($overflow) {
  804.  804                         $ciphertext.= openssl_encrypt(substr($plaintext0, -$overflow) . str_repeat("\0"$this->block_size), $this->cipher_name_openssl$this->key$this->openssl_options$iv);
  805.  805                         $iv $this->_string_pop($ciphertext$this->block_size);
  806.  806 
  807.  807                         $size $len $overflow;
  808.  808                         $block $iv substr($plaintext, -$overflow);
  809.  809                         $iv substr_replace($iv$block0$overflow);
  810.  810                         $ciphertext.= $block;
  811.  811                         $pos $overflow;
  812.  812                     } elseif ($len) {
  813.  813                         $ciphertext openssl_encrypt($plaintext$this->cipher_name_openssl$this->key$this->openssl_options$iv);
  814.  814                         $iv substr($ciphertext, -$this->block_size);
  815.  815                     }
  816.  816 
  817.  817                     return $ciphertext;
  818.  818                 case CRYPT_MODE_OFB:
  819.  819                     return $this->_openssl_ofb_process($plaintext$this->encryptIV$this->enbuffer);
  820.  820             }
  821.  821         }
  822.  822 
  823.  823         if ($this->engine === CRYPT_ENGINE_MCRYPT) {
  824.  824             if ($this->changed) {
  825.  825                 $this->_setupMcrypt();
  826.  826                 $this->changed false;
  827.  827             }
  828.  828             if ($this->enchanged) {
  829.  829                 @mcrypt_generic_init($this->enmcrypt$this->key$this->encryptIV);
  830.  830                 $this->enchanged false;
  831.  831             }
  832.  832 
  833.  833             // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
  834.  834             // using mcrypt's default handing of CFB the above would output two different things.  using phpseclib's
  835.  835             // rewritten CFB implementation the above outputs the same thing twice.
  836.  836             if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
  837.  837                 $block_size $this->block_size;
  838.  838                 $iv = &$this->encryptIV;
  839.  839                 $pos = &$this->enbuffer['pos'];
  840.  840                 $len strlen($plaintext);
  841.  841                 $ciphertext '';
  842.  842                 $i 0;
  843.  843                 if ($pos) {
  844.  844                     $orig_pos $pos;
  845.  845                     $max $block_size $pos;
  846.  846                     if ($len >= $max) {
  847.  847                         $i $max;
  848.  848                         $len-= $max;
  849.  849                         $pos 0;
  850.  850                     } else {
  851.  851                         $i $len;
  852.  852                         $pos+= $len;
  853.  853                         $len 0;
  854.  854                     }
  855.  855                     $ciphertext substr($iv$orig_pos) ^ $plaintext;
  856.  856                     $iv substr_replace($iv$ciphertext$orig_pos$i);
  857.  857                     $this->enbuffer['enmcrypt_init'] = true;
  858.  858                 }
  859.  859                 if ($len >= $block_size) {
  860.  860                     if ($this->enbuffer['enmcrypt_init'] === false || $len $this->cfb_init_len) {
  861.  861                         if ($this->enbuffer['enmcrypt_init'] === true) {
  862.  862                             @mcrypt_generic_init($this->enmcrypt$this->key$iv);
  863.  863                             $this->enbuffer['enmcrypt_init'] = false;
  864.  864                         }
  865.  865                         $ciphertext.= @mcrypt_generic($this->enmcryptsubstr($plaintext$i$len $len $block_size));
  866.  866                         $iv substr($ciphertext, -$block_size);
  867.  867                         $len%= $block_size;
  868.  868                     } else {
  869.  869                         while ($len >= $block_size) {
  870.  870                             $iv = @mcrypt_generic($this->ecb$iv) ^ substr($plaintext$i$block_size);
  871.  871                             $ciphertext.= $iv;
  872.  872                             $len-= $block_size;
  873.  873                             $i+= $block_size;
  874.  874                         }
  875.  875                     }
  876.  876                 }
  877.  877 
  878.  878                 if ($len) {
  879.  879                     $iv = @mcrypt_generic($this->ecb$iv);
  880.  880                     $block $iv substr($plaintext, -$len);
  881.  881                     $iv substr_replace($iv$block0$len);
  882.  882                     $ciphertext.= $block;
  883.  883                     $pos $len;
  884.  884                 }
  885.  885 
  886.  886                 return $ciphertext;
  887.  887             }
  888.  888 
  889.  889             $ciphertext = @mcrypt_generic($this->enmcrypt$plaintext);
  890.  890 
  891.  891             if (!$this->continuousBuffer) {
  892.  892                 @mcrypt_generic_init($this->enmcrypt$this->key$this->encryptIV);
  893.  893             }
  894.  894 
  895.  895             return $ciphertext;
  896.  896         }
  897.  897 
  898.  898         if ($this->changed) {
  899.  899             $this->_setup();
  900.  900             $this->changed false;
  901.  901         }
  902.  902         if ($this->use_inline_crypt) {
  903.  903             $inline $this->inline_crypt;
  904.  904             return $inline('encrypt'$this$plaintext);
  905.  905         }
  906.  906 
  907.  907         $buffer = &$this->enbuffer;
  908.  908         $block_size $this->block_size;
  909.  909         $ciphertext '';
  910.  910         switch ($this->mode) {
  911.  911             case CRYPT_MODE_ECB:
  912.  912                 for ($i 0$i strlen($plaintext); $i+=$block_size) {
  913.  913                     $ciphertext.= $this->_encryptBlock(substr($plaintext$i$block_size));
  914.  914                 }
  915.  915                 break;
  916.  916             case CRYPT_MODE_CBC:
  917.  917                 $xor $this->encryptIV;
  918.  918                 for ($i 0$i strlen($plaintext); $i+=$block_size) {
  919.  919                     $block substr($plaintext$i$block_size);
  920.  920                     $block $this->_encryptBlock($block $xor);
  921.  921                     $xor $block;
  922.  922                     $ciphertext.= $block;
  923.  923                 }
  924.  924                 if ($this->continuousBuffer) {
  925.  925                     $this->encryptIV $xor;
  926.  926                 }
  927.  927                 break;
  928.  928             case CRYPT_MODE_CTR:
  929.  929                 $xor $this->encryptIV;
  930.  930                 if (strlen($buffer['ciphertext'])) {
  931.  931                     for ($i 0$i strlen($plaintext); $i+=$block_size) {
  932.  932                         $block substr($plaintext$i$block_size);
  933.  933                         if (strlen($block) > strlen($buffer['ciphertext'])) {
  934.  934                             $buffer['ciphertext'].= $this->_encryptBlock($xor);
  935.  935                         }
  936.  936                         $this->_increment_str($xor);
  937.  937                         $key $this->_string_shift($buffer['ciphertext'], $block_size);
  938.  938                         $ciphertext.= $block $key;
  939.  939                     }
  940.  940                 } else {
  941.  941                     for ($i 0$i strlen($plaintext); $i+=$block_size) {
  942.  942                         $block substr($plaintext$i$block_size);
  943.  943                         $key $this->_encryptBlock($xor);
  944.  944                         $this->_increment_str($xor);
  945.  945                         $ciphertext.= $block $key;
  946.  946                     }
  947.  947                 }
  948.  948                 if ($this->continuousBuffer) {
  949.  949                     $this->encryptIV $xor;
  950.  950                     if ($start strlen($plaintext) % $block_size) {
  951.  951                         $buffer['ciphertext'] = substr($key$start) . $buffer['ciphertext'];
  952.  952                     }
  953.  953                 }
  954.  954                 break;
  955.  955             case CRYPT_MODE_CFB:
  956.  956                 // cfb loosely routines inspired by openssl's:
  957.  957                 // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
  958.  958                 if ($this->continuousBuffer) {
  959.  959                     $iv = &$this->encryptIV;
  960.  960                     $pos = &$buffer['pos'];
  961.  961                 } else {
  962.  962                     $iv $this->encryptIV;
  963.  963                     $pos 0;
  964.  964                 }
  965.  965                 $len strlen($plaintext);
  966.  966                 $i 0;
  967.  967                 if ($pos) {
  968.  968                     $orig_pos $pos;
  969.  969                     $max $block_size $pos;
  970.  970                     if ($len >= $max) {
  971.  971                         $i $max;
  972.  972                         $len-= $max;
  973.  973                         $pos 0;
  974.  974                     } else {
  975.  975                         $i $len;
  976.  976                         $pos+= $len;
  977.  977                         $len 0;
  978.  978                     }
  979.  979                     // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
  980.  980                     $ciphertext substr($iv$orig_pos) ^ $plaintext;
  981.  981                     $iv substr_replace($iv$ciphertext$orig_pos$i);
  982.  982                 }
  983.  983                 while ($len >= $block_size) {
  984.  984                     $iv $this->_encryptBlock($iv) ^ substr($plaintext$i$block_size);
  985.  985                     $ciphertext.= $iv;
  986.  986                     $len-= $block_size;
  987.  987                     $i+= $block_size;
  988.  988                 }
  989.  989                 if ($len) {
  990.  990                     $iv $this->_encryptBlock($iv);
  991.  991                     $block $iv substr($plaintext$i);
  992.  992                     $iv substr_replace($iv$block0$len);
  993.  993                     $ciphertext.= $block;
  994.  994                     $pos $len;
  995.  995                 }
  996.  996                 break;
  997.  997             case CRYPT_MODE_OFB:
  998.  998                 $xor $this->encryptIV;
  999.  999                 if (strlen($buffer['xor'])) {
  1000. 1000                     for ($i 0$i strlen($plaintext); $i+=$block_size) {
  1001. 1001                         $block substr($plaintext$i$block_size);
  1002. 1002                         if (strlen($block) > strlen($buffer['xor'])) {
  1003. 1003                             $xor $this->_encryptBlock($xor);
  1004. 1004                             $buffer['xor'].= $xor;
  1005. 1005                         }
  1006. 1006                         $key $this->_string_shift($buffer['xor'], $block_size);
  1007. 1007                         $ciphertext.= $block $key;
  1008. 1008                     }
  1009. 1009                 } else {
  1010. 1010                     for ($i 0$i strlen($plaintext); $i+=$block_size) {
  1011. 1011                         $xor $this->_encryptBlock($xor);
  1012. 1012                         $ciphertext.= substr($plaintext$i$block_size) ^ $xor;
  1013. 1013                     }
  1014. 1014                     $key $xor;
  1015. 1015                 }
  1016. 1016                 if ($this->continuousBuffer) {
  1017. 1017                     $this->encryptIV $xor;
  1018. 1018                     if ($start strlen($plaintext) % $block_size) {
  1019. 1019                         $buffer['xor'] = substr($key$start) . $buffer['xor'];
  1020. 1020                     }
  1021. 1021                 }
  1022. 1022                 break;
  1023. 1023             case CRYPT_MODE_STREAM:
  1024. 1024                 $ciphertext $this->_encryptBlock($plaintext);
  1025. 1025                 break;
  1026. 1026         }
  1027. 1027 
  1028. 1028         return $ciphertext;
  1029. 1029     }
  1030. 1030 
  1031. 1031     /**
  1032. 1032      * Decrypts a message.
  1033. 1033      *
  1034. 1034      * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
  1035. 1035      * it is.
  1036. 1036      *
  1037. 1037      * @see self::encrypt()
  1038. 1038      * @access public
  1039. 1039      * @param string $ciphertext
  1040. 1040      * @return string $plaintext
  1041. 1041      * @internal Could, but not must, extend by the child Crypt_* class
  1042. 1042      */
  1043. 1043     function decrypt($ciphertext)
  1044. 1044     {
  1045. 1045         if ($this->paddable) {
  1046. 1046             // we pad with chr(0) since that's what mcrypt_generic does.  to quote from {@link http://www.php.net/function.mcrypt-generic}:
  1047. 1047             // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
  1048. 1048             $ciphertext str_pad($ciphertextstrlen($ciphertext) + ($this->block_size strlen($ciphertext) % $this->block_size) % $this->block_sizechr(0));
  1049. 1049         }
  1050. 1050 
  1051. 1051         if ($this->engine === CRYPT_ENGINE_OPENSSL) {
  1052. 1052             if ($this->changed) {
  1053. 1053                 $this->_clearBuffers();
  1054. 1054                 $this->changed false;
  1055. 1055             }
  1056. 1056             switch ($this->mode) {
  1057. 1057                 case CRYPT_MODE_STREAM:
  1058. 1058                     $plaintext openssl_decrypt($ciphertext$this->cipher_name_openssl$this->key$this->openssl_options);
  1059. 1059                     break;
  1060. 1060                 case CRYPT_MODE_ECB:
  1061. 1061                     if (!defined('OPENSSL_RAW_DATA')) {
  1062. 1062                         $ciphertext.= openssl_encrypt(''$this->cipher_name_openssl_ecb$this->keytrue);
  1063. 1063                     }
  1064. 1064                     $plaintext openssl_decrypt($ciphertext$this->cipher_name_openssl$this->key$this->openssl_options);
  1065. 1065                     break;
  1066. 1066                 case CRYPT_MODE_CBC:
  1067. 1067                     if (!defined('OPENSSL_RAW_DATA')) {
  1068. 1068                         $padding str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
  1069. 1069                         $ciphertext.= substr(openssl_encrypt($padding$this->cipher_name_openssl_ecb$this->keytrue), 0$this->block_size);
  1070. 1070                         $offset $this->block_size;
  1071. 1071                     } else {
  1072. 1072                         $offset $this->block_size;
  1073. 1073                     }
  1074. 1074                     $plaintext openssl_decrypt($ciphertext$this->cipher_name_openssl$this->key$this->openssl_options$this->decryptIV);
  1075. 1075                     if ($this->continuousBuffer) {
  1076. 1076                         $this->decryptIV substr($ciphertext, -$offset$this->block_size);
  1077. 1077                     }
  1078. 1078                     break;
  1079. 1079                 case CRYPT_MODE_CTR:
  1080. 1080                     $plaintext $this->_openssl_ctr_process($ciphertext$this->decryptIV$this->debuffer);
  1081. 1081                     break;
  1082. 1082                 case CRYPT_MODE_CFB:
  1083. 1083                     // cfb loosely routines inspired by openssl's:
  1084. 1084                     // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
  1085. 1085                     $plaintext '';
  1086. 1086                     if ($this->continuousBuffer) {
  1087. 1087                         $iv = &$this->decryptIV;
  1088. 1088                         $pos = &$this->buffer['pos'];
  1089. 1089                     } else {
  1090. 1090                         $iv $this->decryptIV;
  1091. 1091                         $pos 0;
  1092. 1092                     }
  1093. 1093                     $len strlen($ciphertext);
  1094. 1094                     $i 0;
  1095. 1095                     if ($pos) {
  1096. 1096                         $orig_pos $pos;
  1097. 1097                         $max $this->block_size $pos;
  1098. 1098                         if ($len >= $max) {
  1099. 1099                             $i $max;
  1100. 1100                             $len-= $max;
  1101. 1101                             $pos 0;
  1102. 1102                         } else {
  1103. 1103                             $i $len;
  1104. 1104                             $pos+= $len;
  1105. 1105                             $len 0;
  1106. 1106                         }
  1107. 1107                         // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
  1108. 1108                         $plaintext substr($iv$orig_pos) ^ $ciphertext;
  1109. 1109                         $iv substr_replace($ivsubstr($ciphertext0$i), $orig_pos$i);
  1110. 1110                         $ciphertext substr($ciphertext$i);
  1111. 1111                     }
  1112. 1112                     $overflow $len $this->block_size;
  1113. 1113                     if ($overflow) {
  1114. 1114                         $plaintext.= openssl_decrypt(substr($ciphertext0, -$overflow), $this->cipher_name_openssl$this->key$this->openssl_options$iv);
  1115. 1115                         if ($len $overflow) {
  1116. 1116                             $iv substr($ciphertext, -$overflow $this->block_size, -$overflow);
  1117. 1117                         }
  1118. 1118                         $iv openssl_encrypt(str_repeat("\0"$this->block_size), $this->cipher_name_openssl$this->key$this->openssl_options$iv);
  1119. 1119                         $plaintext.= $iv substr($ciphertext, -$overflow);
  1120. 1120                         $iv substr_replace($ivsubstr($ciphertext, -$overflow), 0$overflow);
  1121. 1121                         $pos $overflow;
  1122. 1122                     } elseif ($len) {
  1123. 1123                         $plaintext.= openssl_decrypt($ciphertext$this->cipher_name_openssl$this->key$this->openssl_options$iv);
  1124. 1124                         $iv substr($ciphertext, -$this->block_size);
  1125. 1125                     }
  1126. 1126                     break;
  1127. 1127                 case CRYPT_MODE_OFB:
  1128. 1128                     $plaintext $this->_openssl_ofb_process($ciphertext$this->decryptIV$this->debuffer);
  1129. 1129             }
  1130. 1130 
  1131. 1131             return $this->paddable $this->_unpad($plaintext) : $plaintext;
  1132. 1132         }
  1133. 1133 
  1134. 1134         if ($this->engine === CRYPT_ENGINE_MCRYPT) {
  1135. 1135             $block_size $this->block_size;
  1136. 1136             if ($this->changed) {
  1137. 1137                 $this->_setupMcrypt();
  1138. 1138                 $this->changed false;
  1139. 1139             }
  1140. 1140             if ($this->dechanged) {
  1141. 1141                 @mcrypt_generic_init($this->demcrypt$this->key$this->decryptIV);
  1142. 1142                 $this->dechanged false;
  1143. 1143             }
  1144. 1144 
  1145. 1145             if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
  1146. 1146                 $iv = &$this->decryptIV;
  1147. 1147                 $pos = &$this->debuffer['pos'];
  1148. 1148                 $len strlen($ciphertext);
  1149. 1149                 $plaintext '';
  1150. 1150                 $i 0;
  1151. 1151                 if ($pos) {
  1152. 1152                     $orig_pos $pos;
  1153. 1153                     $max $block_size $pos;
  1154. 1154                     if ($len >= $max) {
  1155. 1155                         $i $max;
  1156. 1156                         $len-= $max;
  1157. 1157                         $pos 0;
  1158. 1158                     } else {
  1159. 1159                         $i $len;
  1160. 1160                         $pos+= $len;
  1161. 1161                         $len 0;
  1162. 1162                     }
  1163. 1163                     // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
  1164. 1164                     $plaintext substr($iv$orig_pos) ^ $ciphertext;
  1165. 1165                     $iv substr_replace($ivsubstr($ciphertext0$i), $orig_pos$i);
  1166. 1166                 }
  1167. 1167                 if ($len >= $block_size) {
  1168. 1168                     $cb substr($ciphertext$i$len $len $block_size);
  1169. 1169                     $plaintext.= @mcrypt_generic($this->ecb$iv $cb) ^ $cb;
  1170. 1170                     $iv substr($cb, -$block_size);
  1171. 1171                     $len%= $block_size;
  1172. 1172                 }
  1173. 1173                 if ($len) {
  1174. 1174                     $iv = @mcrypt_generic($this->ecb$iv);
  1175. 1175                     $plaintext.= $iv substr($ciphertext, -$len);
  1176. 1176                     $iv substr_replace($ivsubstr($ciphertext, -$len), 0$len);
  1177. 1177                     $pos $len;
  1178. 1178                 }
  1179. 1179 
  1180. 1180                 return $plaintext;
  1181. 1181             }
  1182. 1182 
  1183. 1183             $plaintext = @mdecrypt_generic($this->demcrypt$ciphertext);
  1184. 1184 
  1185. 1185             if (!$this->continuousBuffer) {
  1186. 1186                 @mcrypt_generic_init($this->demcrypt$this->key$this->decryptIV);
  1187. 1187             }
  1188. 1188 
  1189. 1189             return $this->paddable $this->_unpad($plaintext) : $plaintext;
  1190. 1190         }
  1191. 1191 
  1192. 1192         if ($this->changed) {
  1193. 1193             $this->_setup();
  1194. 1194             $this->changed false;
  1195. 1195         }
  1196. 1196         if ($this->use_inline_crypt) {
  1197. 1197             $inline $this->inline_crypt;
  1198. 1198             return $inline('decrypt'$this$ciphertext);
  1199. 1199         }
  1200. 1200 
  1201. 1201         $block_size $this->block_size;
  1202. 1202 
  1203. 1203         $buffer = &$this->debuffer;
  1204. 1204         $plaintext '';
  1205. 1205         switch ($this->mode) {
  1206. 1206             case CRYPT_MODE_ECB:
  1207. 1207                 for ($i 0$i strlen($ciphertext); $i+=$block_size) {
  1208. 1208                     $plaintext.= $this->_decryptBlock(substr($ciphertext$i$block_size));
  1209. 1209                 }
  1210. 1210                 break;
  1211. 1211             case CRYPT_MODE_CBC:
  1212. 1212                 $xor $this->decryptIV;
  1213. 1213                 for ($i 0$i strlen($ciphertext); $i+=$block_size) {
  1214. 1214                     $block substr($ciphertext$i$block_size);
  1215. 1215                     $plaintext.= $this->_decryptBlock($block) ^ $xor;
  1216. 1216                     $xor $block;
  1217. 1217                 }
  1218. 1218                 if ($this->continuousBuffer) {
  1219. 1219                     $this->decryptIV $xor;
  1220. 1220                 }
  1221. 1221                 break;
  1222. 1222             case CRYPT_MODE_CTR:
  1223. 1223                 $xor $this->decryptIV;
  1224. 1224                 if (strlen($buffer['ciphertext'])) {
  1225. 1225                     for ($i 0$i strlen($ciphertext); $i+=$block_size) {
  1226. 1226                         $block substr($ciphertext$i$block_size);
  1227. 1227                         if (strlen($block) > strlen($buffer['ciphertext'])) {
  1228. 1228                             $buffer['ciphertext'].= $this->_encryptBlock($xor);
  1229. 1229                             $this->_increment_str($xor);
  1230. 1230                         }
  1231. 1231                         $key $this->_string_shift($buffer['ciphertext'], $block_size);
  1232. 1232                         $plaintext.= $block $key;
  1233. 1233                     }
  1234. 1234                 } else {
  1235. 1235                     for ($i 0$i strlen($ciphertext); $i+=$block_size) {
  1236. 1236                         $block substr($ciphertext$i$block_size);
  1237. 1237                         $key $this->_encryptBlock($xor);
  1238. 1238                         $this->_increment_str($xor);
  1239. 1239                         $plaintext.= $block $key;
  1240. 1240                     }
  1241. 1241                 }
  1242. 1242                 if ($this->continuousBuffer) {
  1243. 1243                     $this->decryptIV $xor;
  1244. 1244                     if ($start strlen($ciphertext) % $block_size) {
  1245. 1245                         $buffer['ciphertext'] = substr($key$start) . $buffer['ciphertext'];
  1246. 1246                     }
  1247. 1247                 }
  1248. 1248                 break;
  1249. 1249             case CRYPT_MODE_CFB:
  1250. 1250                 if ($this->continuousBuffer) {
  1251. 1251                     $iv = &$this->decryptIV;
  1252. 1252                     $pos = &$buffer['pos'];
  1253. 1253                 } else {
  1254. 1254                     $iv $this->decryptIV;
  1255. 1255                     $pos 0;
  1256. 1256                 }
  1257. 1257                 $len strlen($ciphertext);
  1258. 1258                 $i 0;
  1259. 1259                 if ($pos) {
  1260. 1260                     $orig_pos $pos;
  1261. 1261                     $max $block_size $pos;
  1262. 1262                     if ($len >= $max) {
  1263. 1263                         $i $max;
  1264. 1264                         $len-= $max;
  1265. 1265                         $pos 0;
  1266. 1266                     } else {
  1267. 1267                         $i $len;
  1268. 1268                         $pos+= $len;
  1269. 1269                         $len 0;
  1270. 1270                     }
  1271. 1271                     // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
  1272. 1272                     $plaintext substr($iv$orig_pos) ^ $ciphertext;
  1273. 1273                     $iv substr_replace($ivsubstr($ciphertext0$i), $orig_pos$i);
  1274. 1274                 }
  1275. 1275                 while ($len >= $block_size) {
  1276. 1276                     $iv $this->_encryptBlock($iv);
  1277. 1277                     $cb substr($ciphertext$i$block_size);
  1278. 1278                     $plaintext.= $iv $cb;
  1279. 1279                     $iv $cb;
  1280. 1280                     $len-= $block_size;
  1281. 1281                     $i+= $block_size;
  1282. 1282                 }
  1283. 1283                 if ($len) {
  1284. 1284                     $iv $this->_encryptBlock($iv);
  1285. 1285                     $plaintext.= $iv substr($ciphertext$i);
  1286. 1286                     $iv substr_replace($ivsubstr($ciphertext$i), 0$len);
  1287. 1287                     $pos $len;
  1288. 1288                 }
  1289. 1289                 break;
  1290. 1290             case CRYPT_MODE_OFB:
  1291. 1291                 $xor $this->decryptIV;
  1292. 1292                 if (strlen($buffer['xor'])) {
  1293. 1293                     for ($i 0$i strlen($ciphertext); $i+=$block_size) {
  1294. 1294                         $block substr($ciphertext$i$block_size);
  1295. 1295                         if (strlen($block) > strlen($buffer['xor'])) {
  1296. 1296                             $xor $this->_encryptBlock($xor);
  1297. 1297                             $buffer['xor'].= $xor;
  1298. 1298                         }
  1299. 1299                         $key $this->_string_shift($buffer['xor'], $block_size);
  1300. 1300                         $plaintext.= $block $key;
  1301. 1301                     }
  1302. 1302                 } else {
  1303. 1303                     for ($i 0$i strlen($ciphertext); $i+=$block_size) {
  1304. 1304                         $xor $this->_encryptBlock($xor);
  1305. 1305                         $plaintext.= substr($ciphertext$i$block_size) ^ $xor;
  1306. 1306                     }
  1307. 1307                     $key $xor;
  1308. 1308                 }
  1309. 1309                 if ($this->continuousBuffer) {
  1310. 1310                     $this->decryptIV $xor;
  1311. 1311                     if ($start strlen($ciphertext) % $block_size) {
  1312. 1312                         $buffer['xor'] = substr($key$start) . $buffer['xor'];
  1313. 1313                     }
  1314. 1314                 }
  1315. 1315                 break;
  1316. 1316             case CRYPT_MODE_STREAM:
  1317. 1317                 $plaintext $this->_decryptBlock($ciphertext);
  1318. 1318                 break;
  1319. 1319         }
  1320. 1320         return $this->paddable $this->_unpad($plaintext) : $plaintext;
  1321. 1321     }
  1322. 1322 
  1323. 1323     /**
  1324. 1324      * OpenSSL CTR Processor
  1325. 1325      *
  1326. 1326      * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
  1327. 1327      * for CTR is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
  1328. 1328      * and Crypt_Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
  1329. 1329      * function will emulate CTR with ECB when necessary.
  1330. 1330      *
  1331. 1331      * @see self::encrypt()
  1332. 1332      * @see self::decrypt()
  1333. 1333      * @param string $plaintext
  1334. 1334      * @param string $encryptIV
  1335. 1335      * @param array $buffer
  1336. 1336      * @return string
  1337. 1337      * @access private
  1338. 1338      */
  1339. 1339     function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
  1340. 1340     {
  1341. 1341         $ciphertext '';
  1342. 1342 
  1343. 1343         $block_size $this->block_size;
  1344. 1344         $key $this->key;
  1345. 1345 
  1346. 1346         if ($this->openssl_emulate_ctr) {
  1347. 1347             $xor $encryptIV;
  1348. 1348             if (strlen($buffer['ciphertext'])) {
  1349. 1349                 for ($i 0$i strlen($plaintext); $i+=$block_size) {
  1350. 1350                     $block substr($plaintext$i$block_size);
  1351. 1351                     if (strlen($block) > strlen($buffer['ciphertext'])) {
  1352. 1352                         $result openssl_encrypt($xor$this->cipher_name_openssl_ecb$key$this->openssl_options);
  1353. 1353                         $result = !defined('OPENSSL_RAW_DATA') ? substr($result0, -$this->block_size) : $result;
  1354. 1354                         $buffer['ciphertext'].= $result;
  1355. 1355                     }
  1356. 1356                     $this->_increment_str($xor);
  1357. 1357                     $otp $this->_string_shift($buffer['ciphertext'], $block_size);
  1358. 1358                     $ciphertext.= $block $otp;
  1359. 1359                 }
  1360. 1360             } else {
  1361. 1361                 for ($i 0$i strlen($plaintext); $i+=$block_size) {
  1362. 1362                     $block substr($plaintext$i$block_size);
  1363. 1363                     $otp openssl_encrypt($xor$this->cipher_name_openssl_ecb$key$this->openssl_options);
  1364. 1364                     $otp = !defined('OPENSSL_RAW_DATA') ? substr($otp0, -$this->block_size) : $otp;
  1365. 1365                     $this->_increment_str($xor);
  1366. 1366                     $ciphertext.= $block $otp;
  1367. 1367                 }
  1368. 1368             }
  1369. 1369             if ($this->continuousBuffer) {
  1370. 1370                 $encryptIV $xor;
  1371. 1371                 if ($start strlen($plaintext) % $block_size) {
  1372. 1372                     $buffer['ciphertext'] = substr($key$start) . $buffer['ciphertext'];
  1373. 1373                 }
  1374. 1374             }
  1375. 1375 
  1376. 1376             return $ciphertext;
  1377. 1377         }
  1378. 1378 
  1379. 1379         if (strlen($buffer['ciphertext'])) {
  1380. 1380             $ciphertext $plaintext $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
  1381. 1381             $plaintext substr($plaintextstrlen($ciphertext));
  1382. 1382 
  1383. 1383             if (!strlen($plaintext)) {
  1384. 1384                 return $ciphertext;
  1385. 1385             }
  1386. 1386         }
  1387. 1387 
  1388. 1388         $overflow strlen($plaintext) % $block_size;
  1389. 1389         if ($overflow) {
  1390. 1390             $plaintext2 $this->_string_pop($plaintext$overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
  1391. 1391             $encrypted openssl_encrypt($plaintext str_repeat("\0"$block_size), $this->cipher_name_openssl$key$this->openssl_options$encryptIV);
  1392. 1392             $temp $this->_string_pop($encrypted$block_size);
  1393. 1393             $ciphertext.= $encrypted . ($plaintext2 $temp);
  1394. 1394             if ($this->continuousBuffer) {
  1395. 1395                 $buffer['ciphertext'] = substr($temp$overflow);
  1396. 1396                 $encryptIV $temp;
  1397. 1397             }
  1398. 1398         } elseif (!strlen($buffer['ciphertext'])) {
  1399. 1399             $ciphertext.= openssl_encrypt($plaintext str_repeat("\0"$block_size), $this->cipher_name_openssl$key$this->openssl_options$encryptIV);
  1400. 1400             $temp $this->_string_pop($ciphertext$block_size);
  1401. 1401             if ($this->continuousBuffer) {
  1402. 1402                 $encryptIV $temp;
  1403. 1403             }
  1404. 1404         }
  1405. 1405         if ($this->continuousBuffer) {
  1406. 1406             if (!defined('OPENSSL_RAW_DATA')) {
  1407. 1407                 $encryptIV.= openssl_encrypt(''$this->cipher_name_openssl_ecb$key$this->openssl_options);
  1408. 1408             }
  1409. 1409             $encryptIV openssl_decrypt($encryptIV$this->cipher_name_openssl_ecb$key$this->openssl_options);
  1410. 1410             if ($overflow) {
  1411. 1411                 $this->_increment_str($encryptIV);
  1412. 1412             }
  1413. 1413         }
  1414. 1414 
  1415. 1415         return $ciphertext;
  1416. 1416     }
  1417. 1417 
  1418. 1418     /**
  1419. 1419      * OpenSSL OFB Processor
  1420. 1420      *
  1421. 1421      * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
  1422. 1422      * for OFB is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
  1423. 1423      * and Crypt_Base::decrypt().
  1424. 1424      *
  1425. 1425      * @see self::encrypt()
  1426. 1426      * @see self::decrypt()
  1427. 1427      * @param string $plaintext
  1428. 1428      * @param string $encryptIV
  1429. 1429      * @param array $buffer
  1430. 1430      * @return string
  1431. 1431      * @access private
  1432. 1432      */
  1433. 1433     function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
  1434. 1434     {
  1435. 1435         if (strlen($buffer['xor'])) {
  1436. 1436             $ciphertext $plaintext $buffer['xor'];
  1437. 1437             $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
  1438. 1438             $plaintext substr($plaintextstrlen($ciphertext));
  1439. 1439         } else {
  1440. 1440             $ciphertext '';
  1441. 1441         }
  1442. 1442 
  1443. 1443         $block_size $this->block_size;
  1444. 1444 
  1445. 1445         $len strlen($plaintext);
  1446. 1446         $key $this->key;
  1447. 1447         $overflow $len $block_size;
  1448. 1448 
  1449. 1449         if (strlen($plaintext)) {
  1450. 1450             if ($overflow) {
  1451. 1451                 $ciphertext.= openssl_encrypt(substr($plaintext0, -$overflow) . str_repeat("\0"$block_size), $this->cipher_name_openssl$key$this->openssl_options$encryptIV);
  1452. 1452                 $xor $this->_string_pop($ciphertext$block_size);
  1453. 1453                 if ($this->continuousBuffer) {
  1454. 1454                     $encryptIV $xor;
  1455. 1455                 }
  1456. 1456                 $ciphertext.= $this->_string_shift($xor$overflow) ^ substr($plaintext, -$overflow);
  1457. 1457                 if ($this->continuousBuffer) {
  1458. 1458                     $buffer['xor'] = $xor;
  1459. 1459                 }
  1460. 1460             } else {
  1461. 1461                 $ciphertext openssl_encrypt($plaintext$this->cipher_name_openssl$key$this->openssl_options$encryptIV);
  1462. 1462                 if ($this->continuousBuffer) {
  1463. 1463                     $encryptIV substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
  1464. 1464                 }
  1465. 1465             }
  1466. 1466         }
  1467. 1467 
  1468. 1468         return $ciphertext;
  1469. 1469     }
  1470. 1470 
  1471. 1471     /**
  1472. 1472      * phpseclib <-> OpenSSL Mode Mapper
  1473. 1473      *
  1474. 1474      * May need to be overwritten by classes extending this one in some cases
  1475. 1475      *
  1476. 1476      * @return int
  1477. 1477      * @access private
  1478. 1478      */
  1479. 1479     function _openssl_translate_mode()
  1480. 1480     {
  1481. 1481         switch ($this->mode) {
  1482. 1482             case CRYPT_MODE_ECB:
  1483. 1483                 return 'ecb';
  1484. 1484             case CRYPT_MODE_CBC:
  1485. 1485                 return 'cbc';
  1486. 1486             case CRYPT_MODE_CTR:
  1487. 1487                 return 'ctr';
  1488. 1488             case CRYPT_MODE_CFB:
  1489. 1489                 return 'cfb';
  1490. 1490             case CRYPT_MODE_OFB:
  1491. 1491                 return 'ofb';
  1492. 1492         }
  1493. 1493     }
  1494. 1494 
  1495. 1495     /**
  1496. 1496      * Pad "packets".
  1497. 1497      *
  1498. 1498      * Block ciphers working by encrypting between their specified [$this->]block_size at a time
  1499. 1499      * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
  1500. 1500      * pad the input so that it is of the proper length.
  1501. 1501      *
  1502. 1502      * Padding is enabled by default.  Sometimes, however, it is undesirable to pad strings.  Such is the case in SSH,
  1503. 1503      * where "packets" are padded with random bytes before being encrypted.  Unpad these packets and you risk stripping
  1504. 1504      * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
  1505. 1505      * transmitted separately)
  1506. 1506      *
  1507. 1507      * @see self::disablePadding()
  1508. 1508      * @access public
  1509. 1509      */
  1510. 1510     function enablePadding()
  1511. 1511     {
  1512. 1512         $this->padding true;
  1513. 1513     }
  1514. 1514 
  1515. 1515     /**
  1516. 1516      * Do not pad packets.
  1517. 1517      *
  1518. 1518      * @see self::enablePadding()
  1519. 1519      * @access public
  1520. 1520      */
  1521. 1521     function disablePadding()
  1522. 1522     {
  1523. 1523         $this->padding false;
  1524. 1524     }
  1525. 1525 
  1526. 1526     /**
  1527. 1527      * Treat consecutive "packets" as if they are a continuous buffer.
  1528. 1528      *
  1529. 1529      * Say you have a 32-byte plaintext $plaintext.  Using the default behavior, the two following code snippets
  1530. 1530      * will yield different outputs:
  1531. 1531      *
  1532. 1532      * <code>
  1533. 1533      *    echo $rijndael->encrypt(substr($plaintext,  0, 16));
  1534. 1534      *    echo $rijndael->encrypt(substr($plaintext, 16, 16));
  1535. 1535      * </code>
  1536. 1536      * <code>
  1537. 1537      *    echo $rijndael->encrypt($plaintext);
  1538. 1538      * </code>
  1539. 1539      *
  1540. 1540      * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates
  1541. 1541      * another, as demonstrated with the following:
  1542. 1542      *
  1543. 1543      * <code>
  1544. 1544      *    $rijndael->encrypt(substr($plaintext, 0, 16));
  1545. 1545      *    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
  1546. 1546      * </code>
  1547. 1547      * <code>
  1548. 1548      *    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
  1549. 1549      * </code>
  1550. 1550      *
  1551. 1551      * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different
  1552. 1552      * outputs.  The reason is due to the fact that the initialization vector's change after every encryption /
  1553. 1553      * decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.
  1554. 1554      *
  1555. 1555      * Put another way, when the continuous buffer is enabled, the state of the Crypt_*() object changes after each
  1556. 1556      * encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that
  1557. 1557      * continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),
  1558. 1558      * however, they are also less intuitive and more likely to cause you problems.
  1559. 1559      *
  1560. 1560      * @see self::disableContinuousBuffer()
  1561. 1561      * @access public
  1562. 1562      * @internal Could, but not must, extend by the child Crypt_* class
  1563. 1563      */
  1564. 1564     function enableContinuousBuffer()
  1565. 1565     {
  1566. 1566         if ($this->mode == CRYPT_MODE_ECB) {
  1567. 1567             return;
  1568. 1568         }
  1569. 1569 
  1570. 1570         $this->continuousBuffer true;
  1571. 1571 
  1572. 1572         $this->_setEngine();
  1573. 1573     }
  1574. 1574 
  1575. 1575     /**
  1576. 1576      * Treat consecutive packets as if they are a discontinuous buffer.
  1577. 1577      *
  1578. 1578      * The default behavior.
  1579. 1579      *
  1580. 1580      * @see self::enableContinuousBuffer()
  1581. 1581      * @access public
  1582. 1582      * @internal Could, but not must, extend by the child Crypt_* class
  1583. 1583      */
  1584. 1584     function disableContinuousBuffer()
  1585. 1585     {
  1586. 1586         if ($this->mode == CRYPT_MODE_ECB) {
  1587. 1587             return;
  1588. 1588         }
  1589. 1589         if (!$this->continuousBuffer) {
  1590. 1590             return;
  1591. 1591         }
  1592. 1592 
  1593. 1593         $this->continuousBuffer false;
  1594. 1594         $this->changed true;
  1595. 1595 
  1596. 1596         $this->_setEngine();
  1597. 1597     }
  1598. 1598 
  1599. 1599     /**
  1600. 1600      * Test for engine validity
  1601. 1601      *
  1602. 1602      * @see self::Crypt_Base()
  1603. 1603      * @param int $engine
  1604. 1604      * @access public
  1605. 1605      * @return bool
  1606. 1606      */
  1607. 1607     function isValidEngine($engine)
  1608. 1608     {
  1609. 1609         switch ($engine) {
  1610. 1610             case CRYPT_ENGINE_OPENSSL:
  1611. 1611                 if ($this->mode == CRYPT_MODE_STREAM && $this->continuousBuffer) {
  1612. 1612                     return false;
  1613. 1613                 }
  1614. 1614                 $this->openssl_emulate_ctr false;
  1615. 1615                 $result $this->cipher_name_openssl &&
  1616. 1616                           extension_loaded('openssl') &&
  1617. 1617                           // PHP 5.3.0 - 5.3.2 did not let you set IV's
  1618. 1618                           version_compare(PHP_VERSION'5.3.3''>=');
  1619. 1619                 if (!$result) {
  1620. 1620                     return false;
  1621. 1621                 }
  1622. 1622 
  1623. 1623                 // prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
  1624. 1624                 // $options openssl_encrypt expected a boolean $raw_data.
  1625. 1625                 if (!defined('OPENSSL_RAW_DATA')) {
  1626. 1626                     $this->openssl_options true;
  1627. 1627                 } else {
  1628. 1628                     $this->openssl_options OPENSSL_RAW_DATA OPENSSL_ZERO_PADDING;
  1629. 1629                 }
  1630. 1630 
  1631. 1631                 $methods openssl_get_cipher_methods();
  1632. 1632                 if (in_array($this->cipher_name_openssl$methods)) {
  1633. 1633                     return true;
  1634. 1634                 }
  1635. 1635                 // not all of openssl's symmetric cipher's support ctr. for those
  1636. 1636                 // that don't we'll emulate it
  1637. 1637                 switch ($this->mode) {
  1638. 1638                     case CRYPT_MODE_CTR:
  1639. 1639                         if (in_array($this->cipher_name_openssl_ecb$methods)) {
  1640. 1640                             $this->openssl_emulate_ctr true;
  1641. 1641                             return true;
  1642. 1642                         }
  1643. 1643                 }
  1644. 1644                 return false;
  1645. 1645             case CRYPT_ENGINE_MCRYPT:
  1646. 1646                 return $this->cipher_name_mcrypt &&
  1647. 1647                        extension_loaded('mcrypt') &&
  1648. 1648                        in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
  1649. 1649             case CRYPT_ENGINE_INTERNAL:
  1650. 1650                 return true;
  1651. 1651         }
  1652. 1652 
  1653. 1653         return false;
  1654. 1654     }
  1655. 1655 
  1656. 1656     /**
  1657. 1657      * Sets the preferred crypt engine
  1658. 1658      *
  1659. 1659      * Currently, $engine could be:
  1660. 1660      *
  1661. 1661      * - CRYPT_ENGINE_OPENSSL  [very fast]
  1662. 1662      *
  1663. 1663      * - CRYPT_ENGINE_MCRYPT   [fast]
  1664. 1664      *
  1665. 1665      * - CRYPT_ENGINE_INTERNAL [slow]
  1666. 1666      *
  1667. 1667      * If the preferred crypt engine is not available the fastest available one will be used
  1668. 1668      *
  1669. 1669      * @see self::Crypt_Base()
  1670. 1670      * @param int $engine
  1671. 1671      * @access public
  1672. 1672      */
  1673. 1673     function setPreferredEngine($engine)
  1674. 1674     {
  1675. 1675         switch ($engine) {
  1676. 1676             //case CRYPT_ENGINE_OPENSSL:
  1677. 1677             case CRYPT_ENGINE_MCRYPT:
  1678. 1678             case CRYPT_ENGINE_INTERNAL:
  1679. 1679                 $this->preferredEngine $engine;
  1680. 1680                 break;
  1681. 1681             default:
  1682. 1682                 $this->preferredEngine CRYPT_ENGINE_OPENSSL;
  1683. 1683         }
  1684. 1684 
  1685. 1685         $this->_setEngine();
  1686. 1686     }
  1687. 1687 
  1688. 1688     /**
  1689. 1689      * Returns the engine currently being utilized
  1690. 1690      *
  1691. 1691      * @see self::_setEngine()
  1692. 1692      * @access public
  1693. 1693      */
  1694. 1694     function getEngine()
  1695. 1695     {
  1696. 1696         return $this->engine;
  1697. 1697     }
  1698. 1698 
  1699. 1699     /**
  1700. 1700      * Sets the engine as appropriate
  1701. 1701      *
  1702. 1702      * @see self::Crypt_Base()
  1703. 1703      * @access private
  1704. 1704      */
  1705. 1705     function _setEngine()
  1706. 1706     {
  1707. 1707         $this->engine null;
  1708. 1708 
  1709. 1709         $candidateEngines = array(
  1710. 1710             $this->preferredEngine,
  1711. 1711             CRYPT_ENGINE_OPENSSL,
  1712. 1712             CRYPT_ENGINE_MCRYPT
  1713. 1713         );
  1714. 1714         foreach ($candidateEngines as $engine) {
  1715. 1715             if ($this->isValidEngine($engine)) {
  1716. 1716                 $this->engine $engine;
  1717. 1717                 break;
  1718. 1718             }
  1719. 1719         }
  1720. 1720         if (!$this->engine) {
  1721. 1721             $this->engine CRYPT_ENGINE_INTERNAL;
  1722. 1722         }
  1723. 1723 
  1724. 1724         if ($this->engine != CRYPT_ENGINE_MCRYPT && $this->enmcrypt) {
  1725. 1725             // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
  1726. 1726             // (re)open them with the module named in $this->cipher_name_mcrypt
  1727. 1727             @mcrypt_module_close($this->enmcrypt);
  1728. 1728             @mcrypt_module_close($this->demcrypt);
  1729. 1729             $this->enmcrypt null;
  1730. 1730             $this->demcrypt null;
  1731. 1731 
  1732. 1732             if ($this->ecb) {
  1733. 1733                 @mcrypt_module_close($this->ecb);
  1734. 1734                 $this->ecb null;
  1735. 1735             }
  1736. 1736         }
  1737. 1737 
  1738. 1738         $this->changed true;
  1739. 1739     }
  1740. 1740 
  1741. 1741     /**
  1742. 1742      * Encrypts a block
  1743. 1743      *
  1744. 1744      * @access private
  1745. 1745      * @param string $in
  1746. 1746      * @return string
  1747. 1747      * @internal Must be extended by the child Crypt_* class
  1748. 1748      */
  1749. 1749     function _encryptBlock($in)
  1750. 1750     {
  1751. 1751         user_error((version_compare(PHP_VERSION'5.0.0''>=')  ? __METHOD__ __FUNCTION__)  . '() must extend by class ' get_class($this), E_USER_ERROR);
  1752. 1752     }
  1753. 1753 
  1754. 1754     /**
  1755. 1755      * Decrypts a block
  1756. 1756      *
  1757. 1757      * @access private
  1758. 1758      * @param string $in
  1759. 1759      * @return string
  1760. 1760      * @internal Must be extended by the child Crypt_* class
  1761. 1761      */
  1762. 1762     function _decryptBlock($in)
  1763. 1763     {
  1764. 1764         user_error((version_compare(PHP_VERSION'5.0.0''>=')  ? __METHOD__ __FUNCTION__)  . '() must extend by class ' get_class($this), E_USER_ERROR);
  1765. 1765     }
  1766. 1766 
  1767. 1767     /**
  1768. 1768      * Setup the key (expansion)
  1769. 1769      *
  1770. 1770      * Only used if $engine == CRYPT_ENGINE_INTERNAL
  1771. 1771      *
  1772. 1772      * @see self::_setup()
  1773. 1773      * @access private
  1774. 1774      * @internal Must be extended by the child Crypt_* class
  1775. 1775      */
  1776. 1776     function _setupKey()
  1777. 1777     {
  1778. 1778         user_error((version_compare(PHP_VERSION'5.0.0''>=')  ? __METHOD__ __FUNCTION__)  . '() must extend by class ' get_class($this), E_USER_ERROR);
  1779. 1779     }
  1780. 1780 
  1781. 1781     /**
  1782. 1782      * Setup the CRYPT_ENGINE_INTERNAL $engine
  1783. 1783      *
  1784. 1784      * (re)init, if necessary, the internal cipher $engine and flush all $buffers
  1785. 1785      * Used (only) if $engine == CRYPT_ENGINE_INTERNAL
  1786. 1786      *
  1787. 1787      * _setup() will be called each time if $changed === true
  1788. 1788      * typically this happens when using one or more of following public methods:
  1789. 1789      *
  1790. 1790      * - setKey()
  1791. 1791      *
  1792. 1792      * - setIV()
  1793. 1793      *
  1794. 1794      * - disableContinuousBuffer()
  1795. 1795      *
  1796. 1796      * - First run of encrypt() / decrypt() with no init-settings
  1797. 1797      *
  1798. 1798      * @see self::setKey()
  1799. 1799      * @see self::setIV()
  1800. 1800      * @see self::disableContinuousBuffer()
  1801. 1801      * @access private
  1802. 1802      * @internal _setup() is always called before en/decryption.
  1803. 1803      * @internal Could, but not must, extend by the child Crypt_* class
  1804. 1804      */
  1805. 1805     function _setup()
  1806. 1806     {
  1807. 1807         $this->_clearBuffers();
  1808. 1808         $this->_setupKey();
  1809. 1809 
  1810. 1810         if ($this->use_inline_crypt) {
  1811. 1811             $this->_setupInlineCrypt();
  1812. 1812         }
  1813. 1813     }
  1814. 1814 
  1815. 1815     /**
  1816. 1816      * Setup the CRYPT_ENGINE_MCRYPT $engine
  1817. 1817      *
  1818. 1818      * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
  1819. 1819      * Used (only) if $engine = CRYPT_ENGINE_MCRYPT
  1820. 1820      *
  1821. 1821      * _setupMcrypt() will be called each time if $changed === true
  1822. 1822      * typically this happens when using one or more of following public methods:
  1823. 1823      *
  1824. 1824      * - setKey()
  1825. 1825      *
  1826. 1826      * - setIV()
  1827. 1827      *
  1828. 1828      * - disableContinuousBuffer()
  1829. 1829      *
  1830. 1830      * - First run of encrypt() / decrypt()
  1831. 1831      *
  1832. 1832      * @see self::setKey()
  1833. 1833      * @see self::setIV()
  1834. 1834      * @see self::disableContinuousBuffer()
  1835. 1835      * @access private
  1836. 1836      * @internal Could, but not must, extend by the child Crypt_* class
  1837. 1837      */
  1838. 1838     function _setupMcrypt()
  1839. 1839     {
  1840. 1840         $this->_clearBuffers();
  1841. 1841         $this->enchanged $this->dechanged true;
  1842. 1842 
  1843. 1843         if (!isset($this->enmcrypt)) {
  1844. 1844             static $mcrypt_modes = array(
  1845. 1845                 CRYPT_MODE_CTR    => 'ctr',
  1846. 1846                 CRYPT_MODE_ECB    => MCRYPT_MODE_ECB,
  1847. 1847                 CRYPT_MODE_CBC    => MCRYPT_MODE_CBC,
  1848. 1848                 CRYPT_MODE_CFB    => 'ncfb',
  1849. 1849                 CRYPT_MODE_OFB    => MCRYPT_MODE_NOFB,
  1850. 1850                 CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM,
  1851. 1851             );
  1852. 1852 
  1853. 1853             $this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt''$mcrypt_modes[$this->mode], '');
  1854. 1854             $this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt''$mcrypt_modes[$this->mode], '');
  1855. 1855 
  1856. 1856             // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
  1857. 1857             // to workaround mcrypt's broken ncfb implementation in buffered mode
  1858. 1858             // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
  1859. 1859             if ($this->mode == CRYPT_MODE_CFB) {
  1860. 1860                 $this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt''MCRYPT_MODE_ECB'');
  1861. 1861             }
  1862. 1862         } // else should mcrypt_generic_deinit be called?
  1863. 1863 
  1864. 1864         if ($this->mode == CRYPT_MODE_CFB) {
  1865. 1865             @mcrypt_generic_init($this->ecb$this->keystr_repeat("\0"$this->block_size));
  1866. 1866         }
  1867. 1867     }
  1868. 1868 
  1869. 1869     /**
  1870. 1870      * Pads a string
  1871. 1871      *
  1872. 1872      * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
  1873. 1873      * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
  1874. 1874      * chr($this->block_size - (strlen($text) % $this->block_size)
  1875. 1875      *
  1876. 1876      * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
  1877. 1877      * and padding will, hence forth, be enabled.
  1878. 1878      *
  1879. 1879      * @see self::_unpad()
  1880. 1880      * @param string $text
  1881. 1881      * @access private
  1882. 1882      * @return string
  1883. 1883      */
  1884. 1884     function _pad($text)
  1885. 1885     {
  1886. 1886         $length strlen($text);
  1887. 1887 
  1888. 1888         if (!$this->padding) {
  1889. 1889             if ($length $this->block_size == 0) {
  1890. 1890                 return $text;
  1891. 1891             } else {
  1892. 1892                 user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
  1893. 1893                 $this->padding true;
  1894. 1894             }
  1895. 1895         }
  1896. 1896 
  1897. 1897         $pad $this->block_size - ($length $this->block_size);
  1898. 1898 
  1899. 1899         return str_pad($text$length $padchr($pad));
  1900. 1900     }
  1901. 1901 
  1902. 1902     /**
  1903. 1903      * Unpads a string.
  1904. 1904      *
  1905. 1905      * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
  1906. 1906      * and false will be returned.
  1907. 1907      *
  1908. 1908      * @see self::_pad()
  1909. 1909      * @param string $text
  1910. 1910      * @access private
  1911. 1911      * @return string
  1912. 1912      */
  1913. 1913     function _unpad($text)
  1914. 1914     {
  1915. 1915         if (!$this->padding) {
  1916. 1916             return $text;
  1917. 1917         }
  1918. 1918 
  1919. 1919         $length ord($text[strlen($text) - 1]);
  1920. 1920 
  1921. 1921         if (!$length || $length $this->block_size) {
  1922. 1922             return false;
  1923. 1923         }
  1924. 1924 
  1925. 1925         return substr($text0, -$length);
  1926. 1926     }
  1927. 1927 
  1928. 1928     /**
  1929. 1929      * Clears internal buffers
  1930. 1930      *
  1931. 1931      * Clearing/resetting the internal buffers is done everytime
  1932. 1932      * after disableContinuousBuffer() or on cipher $engine (re)init
  1933. 1933      * ie after setKey() or setIV()
  1934. 1934      *
  1935. 1935      * @access public
  1936. 1936      * @internal Could, but not must, extend by the child Crypt_* class
  1937. 1937      */
  1938. 1938     function _clearBuffers()
  1939. 1939     {
  1940. 1940         $this->enbuffer $this->debuffer = array('ciphertext' => '''xor' => '''pos' => 0'enmcrypt_init' => true);
  1941. 1941 
  1942. 1942         // mcrypt's handling of invalid's $iv:
  1943. 1943         // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
  1944. 1944         $this->encryptIV $this->decryptIV str_pad(substr($this->iv0$this->block_size), $this->block_size"\0");
  1945. 1945 
  1946. 1946         if (!$this->skip_key_adjustment) {
  1947. 1947             $this->key str_pad(substr($this->key0$this->key_length), $this->key_length"\0");
  1948. 1948         }
  1949. 1949     }
  1950. 1950 
  1951. 1951     /**
  1952. 1952      * String Shift
  1953. 1953      *
  1954. 1954      * Inspired by array_shift
  1955. 1955      *
  1956. 1956      * @param string $string
  1957. 1957      * @param int $index
  1958. 1958      * @access private
  1959. 1959      * @return string
  1960. 1960      */
  1961. 1961     function _string_shift(&$string$index 1)
  1962. 1962     {
  1963. 1963         $substr substr($string0$index);
  1964. 1964         $string substr($string$index);
  1965. 1965         return $substr;
  1966. 1966     }
  1967. 1967 
  1968. 1968     /**
  1969. 1969      * String Pop
  1970. 1970      *
  1971. 1971      * Inspired by array_pop
  1972. 1972      *
  1973. 1973      * @param string $string
  1974. 1974      * @param int $index
  1975. 1975      * @access private
  1976. 1976      * @return string
  1977. 1977      */
  1978. 1978     function _string_pop(&$string$index 1)
  1979. 1979     {
  1980. 1980         $substr substr($string, -$index);
  1981. 1981         $string substr($string0, -$index);
  1982. 1982         return $substr;
  1983. 1983     }
  1984. 1984 
  1985. 1985     /**
  1986. 1986      * Increment the current string
  1987. 1987      *
  1988. 1988      * @see self::decrypt()
  1989. 1989      * @see self::encrypt()
  1990. 1990      * @param string $var
  1991. 1991      * @access private
  1992. 1992      */
  1993. 1993     function _increment_str(&$var)
  1994. 1994     {
  1995. 1995         for ($i 4$i <= strlen($var); $i+= 4) {
  1996. 1996             $temp substr($var, -$i4);
  1997. 1997             switch ($temp) {
  1998. 1998                 case "\xFF\xFF\xFF\xFF":
  1999. 1999                     $var substr_replace($var"\x00\x00\x00\x00", -$i4);
  2000. 2000                     break;
  2001. 2001                 case "\x7F\xFF\xFF\xFF":
  2002. 2002                     $var substr_replace($var"\x80\x00\x00\x00", -$i4);
  2003. 2003                     return;
  2004. 2004                 default:
  2005. 2005                     $temp unpack('Nnum'$temp);
  2006. 2006                     $var substr_replace($varpack('N'$temp['num'] + 1), -$i4);
  2007. 2007                     return;
  2008. 2008             }
  2009. 2009         }
  2010. 2010 
  2011. 2011         $remainder strlen($var) % 4;
  2012. 2012 
  2013. 2013         if ($remainder == 0) {
  2014. 2014             return;
  2015. 2015         }
  2016. 2016 
  2017. 2017         $temp unpack('Nnum'str_pad(substr($var0$remainder), 4"\0"STR_PAD_LEFT));
  2018. 2018         $temp substr(pack('N'$temp['num'] + 1), -$remainder);
  2019. 2019         $var substr_replace($var$temp0$remainder);
  2020. 2020     }
  2021. 2021 
  2022. 2022     /**
  2023. 2023      * Setup the performance-optimized function for de/encrypt()
  2024. 2024      *
  2025. 2025      * Stores the created (or existing) callback function-name
  2026. 2026      * in $this->inline_crypt
  2027. 2027      *
  2028. 2028      * Internally for phpseclib developers:
  2029. 2029      *
  2030. 2030      *     _setupInlineCrypt() would be called only if:
  2031. 2031      *
  2032. 2032      *     - $engine == CRYPT_ENGINE_INTERNAL and
  2033. 2033      *
  2034. 2034      *     - $use_inline_crypt === true
  2035. 2035      *
  2036. 2036      *     - each time on _setup(), after(!) _setupKey()
  2037. 2037      *
  2038. 2038      *
  2039. 2039      *     This ensures that _setupInlineCrypt() has always a
  2040. 2040      *     full ready2go initializated internal cipher $engine state
  2041. 2041      *     where, for example, the keys allready expanded,
  2042. 2042      *     keys/block_size calculated and such.
  2043. 2043      *
  2044. 2044      *     It is, each time if called, the responsibility of _setupInlineCrypt():
  2045. 2045      *
  2046. 2046      *     - to set $this->inline_crypt to a valid and fully working callback function
  2047. 2047      *       as a (faster) replacement for encrypt() / decrypt()
  2048. 2048      *
  2049. 2049      *     - NOT to create unlimited callback functions (for memory reasons!)
  2050. 2050      *       no matter how often _setupInlineCrypt() would be called. At some
  2051. 2051      *       point of amount they must be generic re-useable.
  2052. 2052      *
  2053. 2053      *     - the code of _setupInlineCrypt() it self,
  2054. 2054      *       and the generated callback code,
  2055. 2055      *       must be, in following order:
  2056. 2056      *       - 100% safe
  2057. 2057      *       - 100% compatible to encrypt()/decrypt()
  2058. 2058      *       - using only php5+ features/lang-constructs/php-extensions if
  2059. 2059      *         compatibility (down to php4) or fallback is provided
  2060. 2060      *       - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
  2061. 2061      *       - >= 10% faster than encrypt()/decrypt() [which is, by the way,
  2062. 2062      *         the reason for the existence of _setupInlineCrypt() :-)]
  2063. 2063      *       - memory-nice
  2064. 2064      *       - short (as good as possible)
  2065. 2065      *
  2066. 2066      * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
  2067. 2067      *       - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class.
  2068. 2068      *       - The following variable names are reserved:
  2069. 2069      *         - $_*  (all variable names prefixed with an underscore)
  2070. 2070      *         - $self (object reference to it self. Do not use $this, but $self instead)
  2071. 2071      *         - $in (the content of $in has to en/decrypt by the generated code)
  2072. 2072      *       - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
  2073. 2073      *
  2074. 2074      *
  2075. 2075      * @see self::_setup()
  2076. 2076      * @see self::_createInlineCryptFunction()
  2077. 2077      * @see self::encrypt()
  2078. 2078      * @see self::decrypt()
  2079. 2079      * @access private
  2080. 2080      * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
  2081. 2081      */
  2082. 2082     function _setupInlineCrypt()
  2083. 2083     {
  2084. 2084         // If, for any reason, an extending Crypt_Base() Crypt_* class
  2085. 2085         // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
  2086. 2086         // ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class,
  2087. 2087         // in the constructor at object instance-time
  2088. 2088         // or, if it's runtime-specific, at runtime
  2089. 2089 
  2090. 2090         $this->use_inline_crypt false;
  2091. 2091     }
  2092. 2092 
  2093. 2093     /**
  2094. 2094      * Creates the performance-optimized function for en/decrypt()
  2095. 2095      *
  2096. 2096      * Internally for phpseclib developers:
  2097. 2097      *
  2098. 2098      *    _createInlineCryptFunction():
  2099. 2099      *
  2100. 2100      *    - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
  2101. 2101      *      with the current [$this->]mode of operation code
  2102. 2102      *
  2103. 2103      *    - create the $inline function, which called by encrypt() / decrypt()
  2104. 2104      *      as its replacement to speed up the en/decryption operations.
  2105. 2105      *
  2106. 2106      *    - return the name of the created $inline callback function
  2107. 2107      *
  2108. 2108      *    - used to speed up en/decryption
  2109. 2109      *
  2110. 2110      *
  2111. 2111      *
  2112. 2112      *    The main reason why can speed up things [up to 50%] this way are:
  2113. 2113      *
  2114. 2114      *    - using variables more effective then regular.
  2115. 2115      *      (ie no use of expensive arrays but integers $k_0, $k_1 ...
  2116. 2116      *      or even, for example, the pure $key[] values hardcoded)
  2117. 2117      *
  2118. 2118      *    - avoiding 1000's of function calls of ie _encryptBlock()
  2119. 2119      *      but inlining the crypt operations.
  2120. 2120      *      in the mode of operation for() loop.
  2121. 2121      *
  2122. 2122      *    - full loop unroll the (sometimes key-dependent) rounds
  2123. 2123      *      avoiding this way ++$i counters and runtime-if's etc...
  2124. 2124      *
  2125. 2125      *    The basic code architectur of the generated $inline en/decrypt()
  2126. 2126      *    lambda function, in pseudo php, is:
  2127. 2127      *
  2128. 2128      *    <code>
  2129. 2129      *    +----------------------------------------------------------------------------------------------+
  2130. 2130      *    | callback $inline = create_function:                                                          |
  2131. 2131      *    | lambda_function_0001_crypt_ECB($action, $text)                                               |
  2132. 2132      *    | {                                                                                            |
  2133. 2133      *    |     INSERT PHP CODE OF:                                                                      |
  2134. 2134      *    |     $cipher_code['init_crypt'];                  // general init code.                       |
  2135. 2135      *    |                                                  // ie: $sbox'es declarations used for       |
  2136. 2136      *    |                                                  //     encrypt and decrypt'ing.             |
  2137. 2137      *    |                                                                                              |
  2138. 2138      *    |     switch ($action) {                                                                       |
  2139. 2139      *    |         case 'encrypt':                                                                      |
  2140. 2140      *    |             INSERT PHP CODE OF:                                                              |
  2141. 2141      *    |             $cipher_code['init_encrypt'];       // encrypt sepcific init code.               |
  2142. 2142      *    |                                                    ie: specified $key or $box                |
  2143. 2143      *    |                                                        declarations for encrypt'ing.         |
  2144. 2144      *    |                                                                                              |
  2145. 2145      *    |             foreach ($ciphertext) {                                                          |
  2146. 2146      *    |                 $in = $block_size of $ciphertext;                                            |
  2147. 2147      *    |                                                                                              |
  2148. 2148      *    |                 INSERT PHP CODE OF:                                                          |
  2149. 2149      *    |                 $cipher_code['encrypt_block'];  // encrypt's (string) $in, which is always:  |
  2150. 2150      *    |                                                 // strlen($in) == $this->block_size          |
  2151. 2151      *    |                                                 // here comes the cipher algorithm in action |
  2152. 2152      *    |                                                 // for encryption.                           |
  2153. 2153      *    |                                                 // $cipher_code['encrypt_block'] has to      |
  2154. 2154      *    |                                                 // encrypt the content of the $in variable   |
  2155. 2155      *    |                                                                                              |
  2156. 2156      *    |                 $plaintext .= $in;                                                           |
  2157. 2157      *    |             }                                                                                |
  2158. 2158      *    |             return $plaintext;                                                               |
  2159. 2159      *    |                                                                                              |
  2160. 2160      *    |         case 'decrypt':                                                                      |
  2161. 2161      *    |             INSERT PHP CODE OF:                                                              |
  2162. 2162      *    |             $cipher_code['init_decrypt'];       // decrypt sepcific init code                |
  2163. 2163      *    |                                                    ie: specified $key or $box                |
  2164. 2164      *    |                                                        declarations for decrypt'ing.         |
  2165. 2165      *    |             foreach ($plaintext) {                                                           |
  2166. 2166      *    |                 $in = $block_size of $plaintext;                                             |
  2167. 2167      *    |                                                                                              |
  2168. 2168      *    |                 INSERT PHP CODE OF:                                                          |
  2169. 2169      *    |                 $cipher_code['decrypt_block'];  // decrypt's (string) $in, which is always   |
  2170. 2170      *    |                                                 // strlen($in) == $this->block_size          |
  2171. 2171      *    |                                                 // here comes the cipher algorithm in action |
  2172. 2172      *    |                                                 // for decryption.                           |
  2173. 2173      *    |                                                 // $cipher_code['decrypt_block'] has to      |
  2174. 2174      *    |                                                 // decrypt the content of the $in variable   |
  2175. 2175      *    |                 $ciphertext .= $in;                                                          |
  2176. 2176      *    |             }                                                                                |
  2177. 2177      *    |             return $ciphertext;                                                              |
  2178. 2178      *    |     }                                                                                        |
  2179. 2179      *    | }                                                                                            |
  2180. 2180      *    +----------------------------------------------------------------------------------------------+
  2181. 2181      *    </code>
  2182. 2182      *
  2183. 2183      *    See also the Crypt_*::_setupInlineCrypt()'s for
  2184. 2184      *    productive inline $cipher_code's how they works.
  2185. 2185      *
  2186. 2186      *    Structure of:
  2187. 2187      *    <code>
  2188. 2188      *    $cipher_code = array(
  2189. 2189      *        'init_crypt'    => (string) '', // optional
  2190. 2190      *        'init_encrypt'  => (string) '', // optional
  2191. 2191      *        'init_decrypt'  => (string) '', // optional
  2192. 2192      *        'encrypt_block' => (string) '', // required
  2193. 2193      *        'decrypt_block' => (string) ''  // required
  2194. 2194      *    );
  2195. 2195      *    </code>
  2196. 2196      *
  2197. 2197      * @see self::_setupInlineCrypt()
  2198. 2198      * @see self::encrypt()
  2199. 2199      * @see self::decrypt()
  2200. 2200      * @param array $cipher_code
  2201. 2201      * @access private
  2202. 2202      * @return string (the name of the created callback function)
  2203. 2203      */
  2204. 2204     function _createInlineCryptFunction($cipher_code)
  2205. 2205     {
  2206. 2206         $block_size $this->block_size;
  2207. 2207 
  2208. 2208         // optional
  2209. 2209         $init_crypt    = isset($cipher_code['init_crypt'])    ? $cipher_code['init_crypt']    : '';
  2210. 2210         $init_encrypt  = isset($cipher_code['init_encrypt'])  ? $cipher_code['init_encrypt']  : '';
  2211. 2211         $init_decrypt  = isset($cipher_code['init_decrypt'])  ? $cipher_code['init_decrypt']  : '';
  2212. 2212         // required
  2213. 2213         $encrypt_block $cipher_code['encrypt_block'];
  2214. 2214         $decrypt_block $cipher_code['decrypt_block'];
  2215. 2215 
  2216. 2216         // Generating mode of operation inline code,
  2217. 2217         // merged with the $cipher_code algorithm
  2218. 2218         // for encrypt- and decryption.
  2219. 2219         switch ($this->mode) {
  2220. 2220             case CRYPT_MODE_ECB:
  2221. 2221                 $encrypt $init_encrypt '
  2222. 2222                     $_ciphertext = "";
  2223. 2223                     $_plaintext_len = strlen($_text);
  2224. 2224 
  2225. 2225                     for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
  2226. 2226                         $in = substr($_text, $_i, '.$block_size.');
  2227. 2227                         '.$encrypt_block.'
  2228. 2228                         $_ciphertext.= $in;
  2229. 2229                     }
  2230. 2230 
  2231. 2231                     return $_ciphertext;
  2232. 2232                     ';
  2233. 2233 
  2234. 2234                 $decrypt $init_decrypt '
  2235. 2235                     $_plaintext = "";
  2236. 2236                     $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
  2237. 2237                     $_ciphertext_len = strlen($_text);
  2238. 2238 
  2239. 2239                     for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
  2240. 2240                         $in = substr($_text, $_i, '.$block_size.');
  2241. 2241                         '.$decrypt_block.'
  2242. 2242                         $_plaintext.= $in;
  2243. 2243                     }
  2244. 2244 
  2245. 2245                     return $self->_unpad($_plaintext);
  2246. 2246                     ';
  2247. 2247                 break;
  2248. 2248             case CRYPT_MODE_CTR:
  2249. 2249                 $encrypt $init_encrypt '
  2250. 2250                     $_ciphertext = "";
  2251. 2251                     $_plaintext_len = strlen($_text);
  2252. 2252                     $_xor = $self->encryptIV;
  2253. 2253                     $_buffer = &$self->enbuffer;
  2254. 2254                     if (strlen($_buffer["ciphertext"])) {
  2255. 2255                         for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
  2256. 2256                             $_block = substr($_text, $_i, '.$block_size.');
  2257. 2257                             if (strlen($_block) > strlen($_buffer["ciphertext"])) {
  2258. 2258                                 $in = $_xor;
  2259. 2259                                 '.$encrypt_block.'
  2260. 2260                                 $self->_increment_str($_xor);
  2261. 2261                                 $_buffer["ciphertext"].= $in;
  2262. 2262                             }
  2263. 2263                             $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
  2264. 2264                             $_ciphertext.= $_block ^ $_key;
  2265. 2265                         }
  2266. 2266                     } else {
  2267. 2267                         for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
  2268. 2268                             $_block = substr($_text, $_i, '.$block_size.');
  2269. 2269                             $in = $_xor;
  2270. 2270                             '.$encrypt_block.'
  2271. 2271                             $self->_increment_str($_xor);
  2272. 2272                             $_key = $in;
  2273. 2273                             $_ciphertext.= $_block ^ $_key;
  2274. 2274                         }
  2275. 2275                     }
  2276. 2276                     if ($self->continuousBuffer) {
  2277. 2277                         $self->encryptIV = $_xor;
  2278. 2278                         if ($_start = $_plaintext_len % '.$block_size.') {
  2279. 2279                             $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
  2280. 2280                         }
  2281. 2281                     }
  2282. 2282 
  2283. 2283                     return $_ciphertext;
  2284. 2284                 ';
  2285. 2285 
  2286. 2286                 $decrypt $init_encrypt '
  2287. 2287                     $_plaintext = "";
  2288. 2288                     $_ciphertext_len = strlen($_text);
  2289. 2289                     $_xor = $self->decryptIV;
  2290. 2290                     $_buffer = &$self->debuffer;
  2291. 2291 
  2292. 2292                     if (strlen($_buffer["ciphertext"])) {
  2293. 2293                         for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
  2294. 2294                             $_block = substr($_text, $_i, '.$block_size.');
  2295. 2295                             if (strlen($_block) > strlen($_buffer["ciphertext"])) {
  2296. 2296                                 $in = $_xor;
  2297. 2297                                 '.$encrypt_block.'
  2298. 2298                                 $self->_increment_str($_xor);
  2299. 2299                                 $_buffer["ciphertext"].= $in;
  2300. 2300                             }
  2301. 2301                             $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
  2302. 2302                             $_plaintext.= $_block ^ $_key;
  2303. 2303                         }
  2304. 2304                     } else {
  2305. 2305                         for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
  2306. 2306                             $_block = substr($_text, $_i, '.$block_size.');
  2307. 2307                             $in = $_xor;
  2308. 2308                             '.$encrypt_block.'
  2309. 2309                             $self->_increment_str($_xor);
  2310. 2310                             $_key = $in;
  2311. 2311                             $_plaintext.= $_block ^ $_key;
  2312. 2312                         }
  2313. 2313                     }
  2314. 2314                     if ($self->continuousBuffer) {
  2315. 2315                         $self->decryptIV = $_xor;
  2316. 2316                         if ($_start = $_ciphertext_len % '.$block_size.') {
  2317. 2317                             $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
  2318. 2318                         }
  2319. 2319                     }
  2320. 2320 
  2321. 2321                     return $_plaintext;
  2322. 2322                     ';
  2323. 2323                 break;
  2324. 2324             case CRYPT_MODE_CFB:
  2325. 2325                 $encrypt $init_encrypt '
  2326. 2326                     $_ciphertext = "";
  2327. 2327                     $_buffer = &$self->enbuffer;
  2328. 2328 
  2329. 2329                     if ($self->continuousBuffer) {
  2330. 2330                         $_iv = &$self->encryptIV;
  2331. 2331                         $_pos = &$_buffer["pos"];
  2332. 2332                     } else {
  2333. 2333                         $_iv = $self->encryptIV;
  2334. 2334                         $_pos = 0;
  2335. 2335                     }
  2336. 2336                     $_len = strlen($_text);
  2337. 2337                     $_i = 0;
  2338. 2338                     if ($_pos) {
  2339. 2339                         $_orig_pos = $_pos;
  2340. 2340                         $_max = '.$block_size.' - $_pos;
  2341. 2341                         if ($_len >= $_max) {
  2342. 2342                             $_i = $_max;
  2343. 2343                             $_len-= $_max;
  2344. 2344                             $_pos = 0;
  2345. 2345                         } else {
  2346. 2346                             $_i = $_len;
  2347. 2347                             $_pos+= $_len;
  2348. 2348                             $_len = 0;
  2349. 2349                         }
  2350. 2350                         $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
  2351. 2351                         $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
  2352. 2352                     }
  2353. 2353                     while ($_len >= '.$block_size.') {
  2354. 2354                         $in = $_iv;
  2355. 2355                         '.$encrypt_block.';
  2356. 2356                         $_iv = $in ^ substr($_text, $_i, '.$block_size.');
  2357. 2357                         $_ciphertext.= $_iv;
  2358. 2358                         $_len-= '.$block_size.';
  2359. 2359                         $_i+= '.$block_size.';
  2360. 2360                     }
  2361. 2361                     if ($_len) {
  2362. 2362                         $in = $_iv;
  2363. 2363                         '.$encrypt_block.'
  2364. 2364                         $_iv = $in;
  2365. 2365                         $_block = $_iv ^ substr($_text, $_i);
  2366. 2366                         $_iv = substr_replace($_iv, $_block, 0, $_len);
  2367. 2367                         $_ciphertext.= $_block;
  2368. 2368                         $_pos = $_len;
  2369. 2369                     }
  2370. 2370                     return $_ciphertext;
  2371. 2371                 ';
  2372. 2372 
  2373. 2373                 $decrypt $init_encrypt '
  2374. 2374                     $_plaintext = "";
  2375. 2375                     $_buffer = &$self->debuffer;
  2376. 2376 
  2377. 2377                     if ($self->continuousBuffer) {
  2378. 2378                         $_iv = &$self->decryptIV;
  2379. 2379                         $_pos = &$_buffer["pos"];
  2380. 2380                     } else {
  2381. 2381                         $_iv = $self->decryptIV;
  2382. 2382                         $_pos = 0;
  2383. 2383                     }
  2384. 2384                     $_len = strlen($_text);
  2385. 2385                     $_i = 0;
  2386. 2386                     if ($_pos) {
  2387. 2387                         $_orig_pos = $_pos;
  2388. 2388                         $_max = '.$block_size.' - $_pos;
  2389. 2389                         if ($_len >= $_max) {
  2390. 2390                             $_i = $_max;
  2391. 2391                             $_len-= $_max;
  2392. 2392                             $_pos = 0;
  2393. 2393                         } else {
  2394. 2394                             $_i = $_len;
  2395. 2395                             $_pos+= $_len;
  2396. 2396                             $_len = 0;
  2397. 2397                         }
  2398. 2398                         $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
  2399. 2399                         $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
  2400. 2400                     }
  2401. 2401                     while ($_len >= '.$block_size.') {
  2402. 2402                         $in = $_iv;
  2403. 2403                         '.$encrypt_block.'
  2404. 2404                         $_iv = $in;
  2405. 2405                         $cb = substr($_text, $_i, '.$block_size.');
  2406. 2406                         $_plaintext.= $_iv ^ $cb;
  2407. 2407                         $_iv = $cb;
  2408. 2408                         $_len-= '.$block_size.';
  2409. 2409                         $_i+= '.$block_size.';
  2410. 2410                     }
  2411. 2411                     if ($_len) {
  2412. 2412                         $in = $_iv;
  2413. 2413                         '.$encrypt_block.'
  2414. 2414                         $_iv = $in;
  2415. 2415                         $_plaintext.= $_iv ^ substr($_text, $_i);
  2416. 2416                         $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
  2417. 2417                         $_pos = $_len;
  2418. 2418                     }
  2419. 2419 
  2420. 2420                     return $_plaintext;
  2421. 2421                     ';
  2422. 2422                 break;
  2423. 2423             case CRYPT_MODE_OFB:
  2424. 2424                 $encrypt $init_encrypt '
  2425. 2425                     $_ciphertext = "";
  2426. 2426                     $_plaintext_len = strlen($_text);
  2427. 2427                     $_xor = $self->encryptIV;
  2428. 2428                     $_buffer = &$self->enbuffer;
  2429. 2429 
  2430. 2430                     if (strlen($_buffer["xor"])) {
  2431. 2431                         for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
  2432. 2432                             $_block = substr($_text, $_i, '.$block_size.');
  2433. 2433                             if (strlen($_block) > strlen($_buffer["xor"])) {
  2434. 2434                                 $in = $_xor;
  2435. 2435                                 '.$encrypt_block.'
  2436. 2436                                 $_xor = $in;
  2437. 2437                                 $_buffer["xor"].= $_xor;
  2438. 2438                             }
  2439. 2439                             $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
  2440. 2440                             $_ciphertext.= $_block ^ $_key;
  2441. 2441                         }
  2442. 2442                     } else {
  2443. 2443                         for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
  2444. 2444                             $in = $_xor;
  2445. 2445                             '.$encrypt_block.'
  2446. 2446                             $_xor = $in;
  2447. 2447                             $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
  2448. 2448                         }
  2449. 2449                         $_key = $_xor;
  2450. 2450                     }
  2451. 2451                     if ($self->continuousBuffer) {
  2452. 2452                         $self->encryptIV = $_xor;
  2453. 2453                         if ($_start = $_plaintext_len % '.$block_size.') {
  2454. 2454                              $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
  2455. 2455                         }
  2456. 2456                     }
  2457. 2457                     return $_ciphertext;
  2458. 2458                     ';
  2459. 2459 
  2460. 2460                 $decrypt $init_encrypt '
  2461. 2461                     $_plaintext = "";
  2462. 2462                     $_ciphertext_len = strlen($_text);
  2463. 2463                     $_xor = $self->decryptIV;
  2464. 2464                     $_buffer = &$self->debuffer;
  2465. 2465 
  2466. 2466                     if (strlen($_buffer["xor"])) {
  2467. 2467                         for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
  2468. 2468                             $_block = substr($_text, $_i, '.$block_size.');
  2469. 2469                             if (strlen($_block) > strlen($_buffer["xor"])) {
  2470. 2470                                 $in = $_xor;
  2471. 2471                                 '.$encrypt_block.'
  2472. 2472                                 $_xor = $in;
  2473. 2473                                 $_buffer["xor"].= $_xor;
  2474. 2474                             }
  2475. 2475                             $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
  2476. 2476                             $_plaintext.= $_block ^ $_key;
  2477. 2477                         }
  2478. 2478                     } else {
  2479. 2479                         for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
  2480. 2480                             $in = $_xor;
  2481. 2481                             '.$encrypt_block.'
  2482. 2482                             $_xor = $in;
  2483. 2483                             $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
  2484. 2484                         }
  2485. 2485                         $_key = $_xor;
  2486. 2486                     }
  2487. 2487                     if ($self->continuousBuffer) {
  2488. 2488                         $self->decryptIV = $_xor;
  2489. 2489                         if ($_start = $_ciphertext_len % '.$block_size.') {
  2490. 2490                              $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
  2491. 2491                         }
  2492. 2492                     }
  2493. 2493                     return $_plaintext;
  2494. 2494                     ';
  2495. 2495                 break;
  2496. 2496             case CRYPT_MODE_STREAM:
  2497. 2497                 $encrypt $init_encrypt '
  2498. 2498                     $_ciphertext = "";
  2499. 2499                     '.$encrypt_block.'
  2500. 2500                     return $_ciphertext;
  2501. 2501                     ';
  2502. 2502                 $decrypt $init_decrypt '
  2503. 2503                     $_plaintext = "";
  2504. 2504                     '.$decrypt_block.'
  2505. 2505                     return $_plaintext;
  2506. 2506                     ';
  2507. 2507                 break;
  2508. 2508             // case CRYPT_MODE_CBC:
  2509. 2509             default:
  2510. 2510                 $encrypt $init_encrypt '
  2511. 2511                     $_ciphertext = "";
  2512. 2512                     $_plaintext_len = strlen($_text);
  2513. 2513 
  2514. 2514                     $in = $self->encryptIV;
  2515. 2515 
  2516. 2516                     for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
  2517. 2517                         $in = substr($_text, $_i, '.$block_size.') ^ $in;
  2518. 2518                         '.$encrypt_block.'
  2519. 2519                         $_ciphertext.= $in;
  2520. 2520                     }
  2521. 2521 
  2522. 2522                     if ($self->continuousBuffer) {
  2523. 2523                         $self->encryptIV = $in;
  2524. 2524                     }
  2525. 2525 
  2526. 2526                     return $_ciphertext;
  2527. 2527                     ';
  2528. 2528 
  2529. 2529                 $decrypt $init_decrypt '
  2530. 2530                     $_plaintext = "";
  2531. 2531                     $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
  2532. 2532                     $_ciphertext_len = strlen($_text);
  2533. 2533 
  2534. 2534                     $_iv = $self->decryptIV;
  2535. 2535 
  2536. 2536                     for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
  2537. 2537                         $in = $_block = substr($_text, $_i, '.$block_size.');
  2538. 2538                         '.$decrypt_block.'
  2539. 2539                         $_plaintext.= $in ^ $_iv;
  2540. 2540                         $_iv = $_block;
  2541. 2541                     }
  2542. 2542 
  2543. 2543                     if ($self->continuousBuffer) {
  2544. 2544                         $self->decryptIV = $_iv;
  2545. 2545                     }
  2546. 2546 
  2547. 2547                     return $self->_unpad($_plaintext);
  2548. 2548                     ';
  2549. 2549                 break;
  2550. 2550         }
  2551. 2551 
  2552. 2552         // Create the $inline function and return its name as string. Ready to run!
  2553. 2553         if (version_compare(PHP_VERSION'5.3.0') >= 0) {
  2554. 2554             eval('$func = function ($_action, &$self, $_text) { ' $init_crypt 'if ($_action == "encrypt") { ' $encrypt ' } else { ' $decrypt ' } };');
  2555. 2555             return $func;
  2556. 2556         }
  2557. 2557 
  2558. 2558         return create_function('$_action, &$self, $_text'$init_crypt 'if ($_action == "encrypt") { ' $encrypt ' } else { ' $decrypt ' }');
  2559. 2559     }
  2560. 2560 
  2561. 2561     /**
  2562. 2562      * Holds the lambda_functions table (classwide)
  2563. 2563      *
  2564. 2564      * Each name of the lambda function, created from
  2565. 2565      * _setupInlineCrypt() && _createInlineCryptFunction()
  2566. 2566      * is stored, classwide (!), here for reusing.
  2567. 2567      *
  2568. 2568      * The string-based index of $function is a classwide
  2569. 2569      * unique value representing, at least, the $mode of
  2570. 2570      * operation (or more... depends of the optimizing level)
  2571. 2571      * for which $mode the lambda function was created.
  2572. 2572      *
  2573. 2573      * @access private
  2574. 2574      * @return array &$functions
  2575. 2575      */
  2576. 2576     function &_getLambdaFunctions()
  2577. 2577     {
  2578. 2578         static $functions = array();
  2579. 2579         return $functions;
  2580. 2580     }
  2581. 2581 
  2582. 2582     /**
  2583. 2583      * Generates a digest from $bytes
  2584. 2584      *
  2585. 2585      * @see self::_setupInlineCrypt()
  2586. 2586      * @access private
  2587. 2587      * @param $bytes
  2588. 2588      * @return string
  2589. 2589      */
  2590. 2590     function _hashInlineCryptFunction($bytes)
  2591. 2591     {
  2592. 2592         if (!defined('CRYPT_BASE_WHIRLPOOL_AVAILABLE')) {
  2593. 2593             define('CRYPT_BASE_WHIRLPOOL_AVAILABLE', (bool)(extension_loaded('hash') && in_array('whirlpool'hash_algos())));
  2594. 2594         }
  2595. 2595 
  2596. 2596         $result '';
  2597. 2597         $hash $bytes;
  2598. 2598 
  2599. 2599         switch (true) {
  2600. 2600             case CRYPT_BASE_WHIRLPOOL_AVAILABLE:
  2601. 2601                 foreach (str_split($bytes64) as $t) {
  2602. 2602                     $hash hash('whirlpool'$hashtrue);
  2603. 2603                     $result .= $t $hash;
  2604. 2604                 }
  2605. 2605                 return $result hash('whirlpool'$hashtrue);
  2606. 2606             default:
  2607. 2607                 $len strlen($bytes);
  2608. 2608                 for ($i 0$i $len$i+=20) {
  2609. 2609                     $t substr($bytes$i20);
  2610. 2610                     $hash pack('H*'sha1($hash));
  2611. 2611                     $result .= $t $hash;
  2612. 2612                 }
  2613. 2613                 return $result pack('H*'sha1($hash));
  2614. 2614         }
  2615. 2615     }
  2616. 2616 
  2617. 2617     /**
  2618. 2618      * Convert float to int
  2619. 2619      *
  2620. 2620      * On 32-bit Linux installs running PHP < 5.3 converting floats to ints doesn't always work
  2621. 2621      *
  2622. 2622      * @access private
  2623. 2623      * @param string $x
  2624. 2624      * @return int
  2625. 2625      */
  2626. 2626     function safe_intval($x)
  2627. 2627     {
  2628. 2628         switch (true) {
  2629. 2629             case is_int($x):
  2630. 2630             // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
  2631. 2631             case version_compare(PHP_VERSION'5.3.0') >= && (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
  2632. 2632             // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
  2633. 2633             case (PHP_OS "\xDF\xDF\xDF") === 'WIN':
  2634. 2634                 return $x;
  2635. 2635         }
  2636. 2636         return (fmod($x0x80000000) & 0x7FFFFFFF) |
  2637. 2637             ((fmod(floor($x 0x80000000), 2) & 1) << 31);
  2638. 2638     }
  2639. 2639 
  2640. 2640     /**
  2641. 2641      * eval()'able string for in-line float to int
  2642. 2642      *
  2643. 2643      * @access private
  2644. 2644      * @return string
  2645. 2645      */
  2646. 2646     function safe_intval_inline()
  2647. 2647     {
  2648. 2648         // on 32-bit linux systems with PHP < 5.3 float to integer conversion is bad
  2649. 2649         switch (true) {
  2650. 2650             case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
  2651. 2651             case version_compare(PHP_VERSION'5.3.0') >= && (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
  2652. 2652             case (PHP_OS "\xDF\xDF\xDF") === 'WIN':
  2653. 2653                 return '%s';
  2654. 2654                 break;
  2655. 2655             default:
  2656. 2656                 $safeint '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
  2657. 2657                 return $safeint '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
  2658. 2658         }
  2659. 2659     }
  2660. 2660 }